예외 처리(Exception Handling)의 모든 것 (try-except, 사용자 정의 예외)
앞서 파이썬 중급 과정의 전체 로드맵과 모듈·패키지 구조를 살펴보았습니다. 이번 글에서는 실무 프로그래밍에서 프로그램의 안정성을 극대화하는 핵심 기술인 예외 처리(Exception Handling)의 모든 것을 완벽하게 파헤쳐 보겠습니다.
1. 예외 처리(Exception Handling)란?
프로그램을 실행하는 도중 예기치 않은 오류(예: 0으로 나누기, 존재하지 않는 파일 열기, 잘못된 사용자 입력 등)가 발생하면 프로그램은 그 즉시 강제 종료됩니다.
예외 처리란 이러한 오류를 사전에 제어하여 프로그램이 중단되지 않도록 막고, 오류 상황에 맞는 적절한 대응 코드나 안내를 실행할 수 있게 해주는 중요한 기법입니다.
2. 기본적인 예외 처리: try-except
파이썬에서는 try 블록에 오류가 발생할 가능성이 있는 코드를 작성하고, except 블록에 오류가 발생했을 때 실행할 대처 코드를 작성합니다.
try:
result = 10 / 0 # 0으로 나누기 예외 발생 지점
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
2.1 예외 객체를 활용한 상세 정보 파악 (as e)
오류가 발생하면 파이썬은 내부적으로 예외 객체를 생성합니다. as e 구문을 사용하면 발생한 오류의 구체적인 메시지나 원인을 변수로 받아 확인할 수 있습니다.
try:
x = 1 / 0
except ZeroDivisionError as e:
print(f"예외가 발생했습니다: {e}")
2.2 다중 예외 처리 및 모든 예외 통합 처리
하나의 try 블록 안에서도 다양한 종류의 에러가 발생할 수 있습니다. 각 에러 타입별로 except를 나누어 처리하거나, 모든 예외의 부모 클래스인 Exception을 이용해 통합 관리할 수 있습니다.
try:
x = int(input("숫자를 입력하세요: "))
result = 10 / x
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
except ValueError:
print("유효한 숫자가 아닙니다.")
except Exception as e:
print(f"알 수 없는 예외 발생: {e}")
3. 완벽한 흐름 제어: else와 finally
try-except 구조 뒤에 else와 finally를 조합하면 프로그램의 흐름을 더욱 세밀하게 제어할 수 있습니다.
-
else블록:try블록의 코드가 오류 없이 성공적으로 실행되었을 때만 실행됩니다. -
finally블록: 예외 발생 여부와 상관없이 무조건 마지막에 실행됩니다. (주로 파일 닫기나 데이터베이스 연결 해제 같은 리소스 정리에 쓰입니다.)
try:
x = int(input("숫자를 입력하세요: "))
result = 10 / x
except (ZeroDivisionError, ValueError) as e:
print(f"오류가 발생했습니다: {e}")
else:
print(f"정상 처리되었습니다. 계산 결과: {result}")
finally:
print("프로그램을 종료합니다.")
4. 의도적인 오류 발생: raise 키워드와 예외 체인
프로그램을 작성하다 보면 특정 조건에서 강제로 에러를 발생시켜 상위 호출 부모 함수로 제어를 넘겨야 할 때가 있습니다. 이때 raise 키워드를 사용합니다.
예외 체인 (raise ... from)
에러를 처리하는 과정에서 새로운 예외를 발생시킬 때, 원래 발생했던 원인 예외를 함께 연결(__cause__)해 주면 디버깅이 훨씬 수월해집니다.
def divide(a, b):
try:
return a / b
except ZeroDivisionError as e:
# 원래 예외(e)를 원인으로 하는 새로운 ValueError 발생
raise ValueError("잘못된 연산 요청입니다.") from e
try:
divide(1, 0)
except ValueError as e:
print(f"잡아낸 예외: {e}")
print(f"원래 원인 예외: {e.__cause__}")
5. 특화된 에러 제어: 사용자 정의 예외 (Custom Exception)
파이썬이 기본 제공하는 예외 클래스 외에도, 개발자가 직접 예외 클래스를 상속받아 사용자 정의 예외를 만들 수 있습니다. 비즈니스 로직 상 허용되지 않는 규칙(예: 음수 입력 방지 등)을 명확하게 처리할 때 유용합니다.
# Exception 클래스를 상속받아 커스텀 예외 정의
class NegativeNumberError(Exception):
"""음수가 입력되었을 때 발생하는 커스텀 예외"""
pass
def check_positive(x):
if x < 0:
raise NegativeNumberError("음수는 허용되지 않습니다.")
return x
try:
num = int(input("양수를 입력하세요: "))
check_positive(num)
except NegativeNumberError as e:
print(f"사용자 정의 예외 처리: {e}")
except ValueError:
print("유효한 숫자가 아닙니다.")