|

파이썬 예외 처리는 어디까지 잡아야 할까: bare except가 위험한 이유

파이썬 예외 처리 bare except 대표 이미지
파이썬 예외 처리는 어디까지 잡아야 할까를 한눈에 정리합니다.

파이썬 예외 처리는 에러를 조용히 숨기는 문법이 아닙니다. 프로그램이 실패할 수 있는 지점을 인정하고, 그 실패를 어디에서 복구할지 정하는 방법입니다.

가장 조심해야 할 습관은 bare except로 모든 예외를 한꺼번에 삼키는 코드입니다. 이런 코드는 진짜 버그와 사용자가 예상한 실패를 구분하지 못하게 만듭니다.


파이썬 예외 처리는 복구 가능한 실패를 잡는 일이다

try except는 실패 가능성이 있는 코드를 감싸고, 특정 예외가 발생했을 때 대체 흐름을 실행하게 합니다. 중요한 점은 모든 실패를 잡는 것이 아니라 지금 자리에서 처리할 수 있는 실패만 잡는 것입니다.

try:
    value = int(user_input)
except ValueError:
    value = 0

이 코드는 숫자로 바꿀 수 없는 입력이라는 예측 가능한 실패만 처리합니다. 파일 시스템 오류나 프로그래밍 버그까지 감추지 않습니다.

bare except가 위험한 이유

try:
    run_job()
except:
    print("failed")

위 코드는 어떤 예외가 났는지 알기 어렵습니다. 오타, 타입 오류, 키보드 인터럽트처럼 숨기면 안 되는 문제까지 같은 방식으로 처리할 수 있습니다.

잡을 예외를 구체적으로 적어야 한다

예상한 실패가 있다면 그 예외 이름을 적는 편이 좋습니다. 이렇게 하면 코드가 어떤 상황을 복구하려는지 읽는 사람에게 드러납니다.

try:
    with open("config.json", "r", encoding="utf-8") as f:
        config = json.load(f)
except FileNotFoundError:
    config = {}
except json.JSONDecodeError as exc:
    raise ValueError("config.json 형식이 올바르지 않습니다") from exc

Exception을 잡을 때도 로그와 재발생을 고민하자

상위 작업 경계에서는 Exception을 넓게 잡아 로그를 남길 수 있습니다. 하지만 그 자리에서 복구할 수 없다면 조용히 넘기지 말고 다시 raise하는 편이 안전합니다.

try:
    process_order(order)
except Exception:
    logger.exception("order processing failed: %s", order.id)
    raise

else와 finally는 흐름을 분리해 준다

  • else: 예외가 없었을 때만 실행할 후속 작업에 사용
  • finally: 성공/실패와 관계없이 반드시 정리해야 하는 작업에 사용
  • with 문: 파일처럼 닫아야 하는 자원은 가능하면 with로 관리

정리

파이썬 예외 처리는 에러를 없애는 기술이 아니라 실패를 분류하는 기술입니다. 구체적인 예외를 잡고, 복구할 수 없는 실패는 로그를 남긴 뒤 다시 드러내는 것이 더 안전합니다.

내부 글은 파이썬 with context manager 이해하기, 파이썬 yield return 차이, 파이썬 dataclass는 왜 쓸까와 함께 보면 좋습니다. 외부 기준은 Python Docs – Errors and Exceptions, Python Docs – Built-in Exceptions를 확인했습니다.

함께보면 좋은 글