2.25. 오류 처리¶
Python에서 대부분의 런타임 문제는 예외(exception) 로 드러납니다 – 무언가 잘못되었음을 알리는 이름이 붙은 구조화된 방식입니다. ValueError, TypeError, KeyError, OSError, MemoryError 가 모두 그 예입니다. 각각은 클래스이며, 예외를 발생(raise) 시키면 현재 호출이 멈추고 주변 코드에서 처리기를 찾습니다.
2.25.1. try / except¶
코드 블록이 발생시키는 예외를 잡으려면 그 블록을 try 로 감쌉니다:
try:
n = int(input_text)
except ValueError:
n = 0
int(...) 변환이 실패하면 제어는 오류를 더 멀리 전파하는 대신 except 블록으로 점프합니다. input_text 가 유효한 정수 문자열이었다면 except 블록은 건너뜁니다.
하나의 try 에는 여러 개의 except 블록을 둘 수 있으며, 각각 서로 다른 종류의 오류를 잡습니다:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python은 순서대로 매칭합니다. 예외 클래스가 맞는 첫 번째 블록이 문제를 처리합니다. (거의 모든 것의 기반 클래스인) Exception 을 잡으면 어떤 오류든 처리합니다. 그렇게 하는 것은 그 대안이 크래시인, 프로그램의 가장 바깥쪽 계층을 위해 남겨 두십시오.
경고
키워드 뒤에 클래스가 없는 빈 except: 는 KeyboardInterrupt 도 잡습니다 – 실행 중인 스크립트를 중단하기 위해 IDE의 stop 버튼을 누를 때 IDE가 보내는 예외입니다. 빈 except: pass 로 감싼 루프는 이 인터럽트를 삼켜 버리고 계속 실행되어, 전원을 껐다 켜는 것 말고는 스크립트를 멈출 방법이 없게 됩니다.
정말로 넓게 잡아야 할 때는 빈 except: 보다 except Exception: 을 선호하십시오. KeyboardInterrupt 는 Exception 이 아니라 BaseException 을 상속하므로, except Exception: 은 stop 버튼이 계속 동작하도록 남겨 둡니다.
2.25.1.1. 예외 검사하기¶
예외에 첨부된 메시지를 읽으려면 as 로 이름을 붙입니다:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
as 로 바인딩된 변수는 except 블록 안에서만 유효합니다.
2.25.2. else와 finally¶
try 블록에는 두 가지 선택적 추가 요소가 있습니다.
else 는 try 가 예외를 발생시키지 않고 끝났을 때만 실행됩니다:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
“성공했을 때 할 일”을 else 에 두면 try 블록이 좁게 유지됩니다 – 실패할 수 있는 줄만 try 에 속합니다.
finally 는 무슨 일이 있어도 끝에 실행됩니다 – try 가 성공했든, 예외가 발생하여 처리되었든, 발생하여 막 전파되려 하든 상관없습니다:
try:
do_work()
finally:
cleanup()
finally 는 항상 실행됩니다. else 는 예외가 없는 경로에서만 실행됩니다.¶
대부분의 획득/해제 패턴에서는 try / finally 쌍보다 컨텍스트 관리자 를 선호하십시오 – 리소스 자체가 자신의 정리를 관리합니다.
2.25.3. 흔한 내장 예외¶
자주 마주치게 될 예외들의 짧은 목록입니다:
ValueError– 타입은 맞지만 값이 잘못된 경우(bytes([300])– 300은 올바른 타입이지만 0..255라는 유효한 바이트 범위를 벗어납니다).TypeError– 타입 자체가 잘못된 경우(len(42)).IndexError– 시퀀스의 끝을 지난 인덱스.AttributeError– 존재하지 않는 속성에 접근하는 경우("abc".foo).OSError– 파일 시스템 또는 I/O 실패.MemoryError– 힙이 부족해진 경우. 메모리가 제한된 런타임에서는 병적인 경우뿐 아니라 정상적인 동작 중에도 일어날 수 있습니다.