파이썬에서는 코드가 비정상적으로 동작하면 오류(Error)와 예외(Exception)가 발생하고, 프로그램 실행이 갑자기 중단됩니다. 파이썬은 try-except 문을 활용한 예외 처리 메커니즘을 제공하여 이러한 상황에 대응할 수 있도록 도와줍니다. 대표적인 내장 예외로는 ArithmeticError, AssertionError, AttributeError, ImportError 등이 있습니다.
하지만 내장 예외만으로는 애플리케이션의 특수한 상황을 표현하기 어려울 때가 있습니다. 이럴 때 직접 예외 클래스를 정의하는 사용자 정의 예외(User-defined Exception)가 유용합니다. 이 글에서는 사용자 정의 예외를 선언하고 활용하는 다양한 방법을 예제와 함께 살펴보겠습니다.
1. 사용자 정의 예외 클래스 만들기
사용자 정의 예외 클래스는 반드시 내장 Exception 클래스를 직접 또는 간접적으로 상속받아야 합니다. 아래 예제에서는 새로운 예외 클래스인 User_Error를 생성하고, 생성자(__init__)와 문자열 표현 메서드(__str__)를 함께 정의했습니다.
예제 코드
# Exception 슈퍼 클래스를 상속받은 MyError 클래스
class User_Error(Exception):
# 생성자 메서드
def __init__(self, value):
self.value = value
# __str__ 출력 함수
def __str__(self):
return(repr(self.value))
try:
raise(User_Error("User defined error"))
# 예외 객체는 error 변수에 저장됨
except User_Error as error:
print('새로운 예외가 발생했습니다:', error.value)실행 결과
새로운 예외가 발생했습니다: User defined error
raise 문으로 의도적으로 예외를 발생시키고, except 블록에서 해당 예외를 잡아 처리하는 기본적인 패턴입니다. 예외 객체에 담긴 값(value)을 참조해 원하는 형태로 오류 메시지를 출력할 수 있습니다.
2. 다중 상속 구조로 여러 예외 클래스 만들기
하나의 모듈이 서로 다른 여러 종류의 오류를 처리해야 하는 경우에는 모듈 전용 기반(Base) 예외 클래스를 만들어 두는 것이 좋습니다. 그리고 각각의 세부 오류를 나타내는 사용자 정의 클래스들이 이 기반 클래스를 상속받도록 설계하면, 예외 체계를 일관성 있게 관리할 수 있습니다.
예제 코드
# 파이썬 사용자 정의 예외 정의
class Error(Exception):
"""다른 예외들의 기반 클래스"""
pass
class Dividebyzero(Error):
"""입력값이 0일 때 발생하는 예외"""
pass
try:
i_num = int(input("숫자를 입력하세요: "))
if i_num == 0:
raise Dividebyzero
except Dividebyzero:
print("입력값이 0입니다. 다시 시도해 주세요!")
print()실행 결과
숫자를 입력하세요: 입력값이 0입니다. 다시 시도해 주세요!
이처럼 공통 기반 클래스를 두면 except Error로 모듈의 모든 커스텀 예외를 한 번에 처리하거나, except Dividebyzero처럼 특정 예외만 골라 세밀하게 처리할 수도 있습니다.
3. 내장 예외(RuntimeError)를 상속받아 활용하기
RuntimeError는 발생한 오류가 기존에 정의된 예외 범주에 속하지 않을 때 파이썬이 자동으로 발생시키는 내장 클래스입니다. 아래 프로그램은 RuntimeError를 기반 클래스로, 사용자 정의 오류를 파생 클래스로 사용하는 방법을 보여줍니다.
예제 코드
# 사용자 정의 오류
class Usererror(RuntimeError):
def __init__(self, arg):
self.args = arg
try:
raise Usererror("userError")
except Usererror as e:
print(e.args)실행 결과
('u', 's', 'e', 'r', 'E', 'r', 'r', 'o', 'r')문자열이 args에 할당되면서 개별 문자들의 튜플 형태로 출력된 점에 유의하세요. 실무에서는 super().__init__(arg)를 호출하거나 문자열을 리스트로 감싸 저장하는 방식으로 의도치 않은 동작을 피하는 것이 좋습니다.
마무리
이번 글에서는 파이썬 3.x 환경에서 사용자 정의 예외를 선언하고 구현하는 세 가지 방법을 알아보았습니다. 핵심은 Exception 또는 적절한 내장 예외 클래스를 상속받는다는 것, 그리고 프로젝트의 성격에 맞게 예외 계층 구조를 설계하는 것입니다. 잘 설계된 커스텀 예외는 오류의 원인을 명확히 드러내고 디버깅과 유지보수를 크게 쉬워지게 해 줍니다.