7.1 커스텀 익셉션 생성
때때로 Python의 표준 익셉션은 애플리케이션의 필요에 완전히 부합하지 않을 수 있다. 그런 경우, 기본 클래스 Exception 또는 다른 적절한 익셉션 클래스를 상속받아 나만의 익셉션을 만들 수 있다.
커스텀 익셉션 생성 기본 사항
커스텀 익셉션을 생성하는 것은 기본 클래스 Exception을 상속받는 새로운 클래스를 정의하는 것을 포함한다. 오류에 대한 추가 정보를 제공하기 위해 클래스에 자체 메소드와 속성을 추가할 수 있다.
간단한 커스텀 익셉션 만들기 예제
단계 1: 커스텀 익셉션 정의하기
class MyCustomError(Exception):
"""커스텀 익셉션을 위한 클래스."""
pass
단계 2: 커스텀 익셉션 사용하기
def check_value(value):
if value < 0:
raise MyCustomError("값은 0보다 작을 수 없습니다")
try:
check_value(-1)
except MyCustomError as e:
print(f"커스텀 익셉션 발생: {e}")
모든 것이 아주 간단하다. 중요한 것은, 당신의 익셉션이 클래스 Exception이나 그 하위 클래스 중 하나에서 상속받아야 한다는 것이다.
7.2 추가 속성이 있는 익셉션 생성
오류에 대한 추가 정보를 전달하기 위해 익셉션 클래스에 속성 및 메소드를 추가할 수 있다.
예제:
class NegativeValueError( Exception ):
"""부정적인 값에 대한 커스텀 익셉션 클래스."""
def __init__(self, value, message = "값은 0보다 작을 수 없습니다"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
추가 속성이 있는 익셉션 사용하기
def check_value(value):
if value < 0:
raise NegativeValueError(value)
try:
check_value(-1)
except NegativeValueError as e:
print(f"커스텀 익셉션 발생: {e}")
우리의 익셉션은 클래스 Exception을 상속받은 클래스입니다. 따라서 모든 다른 클래스와 같은 방식으로 필드, 메소드, 생성자 매개 변수 등을 추가할 수 있습니다.
모든 것은 당신과 이 익셉션을 처리할 다른 개발자들의 편리함을 위한 것입니다.
7.3 커스텀 익셉션의 계층 구조 만들기
더 복잡한 애플리케이션을 위해 커스텀 익셉션의 계층 구조를 만드는 것이 유용하다. 이는 관련된 익셉션을 그룹화하고 그 처리를 쉽게 한다.
예제:
class ApplicationError(Exception):
"""모든 애플리케이션 익셉션에 대한 기본 클래스."""
pass
class NegativeValueError(ApplicationError):
"""부정적인 값에 대한 커스텀 익셉션 클래스."""
def __init__(self, value, message="값은 0보다 작을 수 없습니다"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
class ValueTooLargeError(ApplicationError):
"""너무 큰 값에 대한 커스텀 익셉션 클래스."""
def __init__(self, value, message="값이 너무 큽니다"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
커스텀 익셉션 계층 구조 사용하기
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except NegativeValueError as e:
print(f"익셉션 발생: {e}")
except ValueTooLargeError as e:
print(f"익셉션 발생: {e}")
except ApplicationError as e:
print(f"일반 애플리케이션 익셉션: {e}")
7.4 익셉션 처리 순서
특히 같은 계층 구조의 익셉션을 처리할 때, 올바른 순서를 지정하는 것이 중요하다. except 블록 내부의 코드는 동시에 실행되지 않지만, 기본 익셉션 클래스는 모든 하위 클래스의 익셉션을 잡아낼 수 있다.
예를 들어, 다음 코드:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except ApplicationError as e: # ApplicationError 타입과 그 모든 하위 클래스 익셉션을 잡아냄
print(f"일반 애플리케이션 익셉션: {e}")
except 블록에서 ApplicationError 타입과 그 모든 하위 클래스의 익셉션이 잡히게 된다.
모든 익셉션은 Exception 클래스의 하위 클래스이므로, 이 코드는 사실 모든 익셉션을 잡아내게 된다:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except Exception as e:
print(f"모든 익셉션 잡음: {e}")
except ApplicationError as e: # 이 코드는 절대 실행되지 않음
print(f"일반 애플리케이션 익셉션: {e}")
except ApplicationError 블록에서의 익셉션 잡기는 절대 발생하지 않으며, except Exception 블록에서 사실상 모든 Exception 타입의 익셉션 및 그 하위 클래스를 잡아낸다.
해결책
따라서 익셉션을 잡는 것은 상속과 반대 순서로 하는 것이 일반적이다: 클래스가 Exception에 가까울수록 아래에 위치한다.
예제:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except NegativeValueError as e:
print(f"익셉션 발생: {e}")
except ApplicationError as e:
print(f"일반 애플리케이션 익셉션: {e}")
except Exception as e:
print(f"모든 익셉션 잡음: {e}")
이 예제에서의 except 블록은 상속 계층에 따라 배치되어 있다: NegativeValueError와 같은 구체적인 익셉션이 먼저 처리되고, 그 다음 ApplicationError와 같은 더 일반적인 익셉션이 처리된다. 이를 통해 더 구체적인 except 블록이 더 일반적인 블록보다 먼저 익셉션을 처리할 수 있게 하여, 익셉션을 올바르게 처리하고, 더 일반적인 except 블록이 모든 것을 잡아내는 상황을 피할 수 있다.
GO TO FULL VERSION