실제 개발 환경에서는 except 절 안의 코드 자체가 또 다른 예외를 발생시키는 상황이 종종 발생합니다. 이럴 때는 중첩된(nested) try-except 구문을 사용하면 except 절에서 발생한 예외까지 효과적으로 처리할 수 있습니다.
예제 코드
다음 예제는 외부 except 절에서 새로운 예외가 발생했을 때, 이를 내부 try-except 블록으로 처리하는 방법을 보여줍니다.
import sys
try:
a = john # 정의되지 않은 변수 → NameError 발생
except:
try:
4 / 0 # except 절 내부에서 ZeroDivisionError 발생
except:
print(sys.exc_info())실행 결과
위 코드를 실행하면 다음과 같은 출력을 얻습니다.
(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x0000000002BD4B88>)코드 동작 방식
이 코드의 실행 흐름은 다음과 같습니다.
1. 외부 try 블록에서 정의되지 않은 변수 john에 접근하여 NameError가 발생합니다.
2. 외부 except 절이 이 예외를 처리하려고 시도하지만, 그 과정에서 4 / 0 연산으로 ZeroDivisionError가 새롭게 발생합니다.
3. 내부 try-except 블록이 이 두 번째 예외를 가로채고, sys.exc_info()를 호출하여 현재 처리 중인 예외 정보를 출력합니다.
sys.exc_info()의 반환 값
sys.exc_info()는 세 개의 요소를 가진 튜플(tuple)을 반환합니다.
- 첫 번째 요소: 발생한 예외의 클래스 (예: ZeroDivisionError)
- 두 번째 요소: 실제 예외 인스턴스와 그 메시지
- 세 번째 요소: 호출 스택 정보를 담은 traceback 객체
참고 사항
Python 3에서는 raise ... from ... 문법을 사용해 예외 간의 인과 관계(cause)를 명시적으로 표현할 수 있으며, 로깅(logging) 모듈의 logger.exception()을 활용하면 예외 발생 지점과 스택 추적 정보를 더 체계적으로 기록할 수 있습니다. 중요한 로직이 포함된 except 절에는 항상 내부 예외 처리를 추가하는 것이 안정적인 프로그램 작성에 도움이 됩니다.