Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬에서 모든 예외를 잡는 try/except 블록 작성 방법

모든 예외를 한 번에 처리하는 코드

파이썬에서는 아래와 같은 코드를 사용해 모든 예외를 한꺼번에 잡을 수 있습니다. 하지만 일반적으로 이러한 방식은 권장되지 않는다는 것이 기본 원칙입니다.

try:
    #do_something()
except:
    print "Exception Caught!"

베어(bare) except 절의 문제점

위 코드의 가장 큰 문제는 개발자가 의도하지 않은 예외까지 모두 잡아버린다는 점입니다. 대표적인 예가 KeyboardInterrupt인데, 사용자가 프로그램을 강제로 종료하려고 Ctrl+C를 눌렀을 때 발생하는 이 예외마저 가려버리면 프로그램이 정상적으로 종료되지 않을 수 있습니다.

또한 예외를 잡은 뒤 적절한 조치 없이 그냥 넘어가면, 실제 오류의 원인을 추적하기 어려워지고 디버깅이 훨씬 힘들어집니다.

올바른 예외 처리 방법: 구체적인 예외 명시와 재발생(re-raise)

예상 가능한 예외는 각각 구체적으로 처리하고, 예상치 못한 예외는 로그를 남긴 후 즉시 다시 발생(re-raise)시키는 것이 좋습니다. 아래 예제를 살펴보겠습니다.

try:
    f = open('file.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise

여기서 마지막 except: 블록은 예상하지 못한 오류 정보를 출력한 뒤 raise를 호출해 예외를 다시 던집니다. 이렇게 하면 프로그램 흐름을 왜곡하지 않으면서도 필요한 정보를 기록할 수 있습니다.

만약 스크립트와 같은 폴더에 file.txt 파일이 존재하지 않는다면, 다음과 같은 결과가 출력됩니다.

I/O error(2): No such file or directory

참고: 파이썬 3에서의 권장 문법

위 예제는 파이썬 2 스타일의 코드입니다. 파이썬 3에서는 튜플 언패킹 방식의 as (errno, strerror) 구문을 지원하지 않으므로, 다음과 같이 작성하는 것이 좋습니다.

import sys

try:
    f = open('file.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as e:
    print("I/O error({0}): {1}".format(e.errno, e.strerror))
except ValueError:
    print("Could not convert data to an integer.")
except Exception:
    print("Unexpected error:", sys.exc_info()[0])
    raise

핵심은 세 가지로 요약할 수 있습니다. 첫째, 가능하면 처리할 예외를 구체적으로 명시할 것. 둘째, 베어 except: 대신 최소한 except Exception:을 사용해 KeyboardInterrupt, SystemExit 같은 시스템 종료 관련 예외는 잡지 않을 것. 셋째, 처리하지 않는 예외는 반드시 raise로 다시 발생시켜 오류를 숨기지 말 것입니다.