PEP 3110 – Python 3000에서 예외 잡기
- Author:
- Collin Winter <collinwinter at google.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 16-Jan-2006
- Python-Version:
- 3.0
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Python의 문법에서 모호성을 제거하고, 예외 클래스를 단순화하며, 예외의 가비지 컬렉션을 간소화하고, Python 3.0에서 언어의 크기를 줄이는 데 도움이 되도록 의도된 변경 사항을 도입합니다.
근거
- Python 2.x의
except절은 파서가 다음 두 경우 중 어느 것인지 구별할 수 없는 구문적 모호성을 나타냅니다.except <expression>, <expression>:
다음으로 해석되어야 하는지
except <type>, <type>:
또는 다음으로 해석되어야 하는지
except <type>, <name>:
Python 2는 후자의 의미를 선택하지만, 그 대가로 전자를 다음과 같이 괄호로 묶어야 합니다.
except (<type>, <type>):
- PEP가 명시한 바에 따라, PEP 352에 예외를 튜플로 취급하는 기능은 제거될 예정이므로 이 코드는 더 이상 작동하지 않습니다.
except os.error, (errno, errstr):
자동 언패킹이 더 이상 가능하지 않으므로, 튜플을
except대상으로 사용할 수 있는 기능을 제거하는 것이 바람직합니다. - PEP가 명시한 바에 따라, PEP 344에서 Python 3의 예외 인스턴스는
__traceback__속성을 갖게 됩니다. 해당 PEP의 미해결 문제 섹션에는 이 속성으로 인해 발생하는 가비지 컬렉션의 어려움을 설명하는 단락이 포함되어 있습니다. 즉, “예외 -> 트레이스백 -> 스택 프레임 -> 예외” 참조 순환으로 인해 다음 GC 실행 때까지 모든 지역 변수가 스코프에 유지됩니다. 이 PEP는 Python 3의except절에 정리 의미를 추가하여 이 문제를 해결하려 합니다. 이에 따라 대상 이름은except스위트의 끝에서 삭제됩니다. - 다음 원칙인 “there should be one – and preferably only one – obvious way to do it”의 취지에 따라 중복 기능을 통합하는 것이 바람직합니다. 이를 위해
sys모듈 [1]의exc_value,exc_type및exc_traceback속성은 동일한 정보를 제공하는sys.exc_info()를 대신 사용하도록 제거됩니다. 이러한 속성은 이미 PEP 3100에서 제거 대상으로 열거되어 있습니다.
문법 변경
Python 3에서는 except 문에 대한 문법이 [4]에서
except_clause: 'except' [test [',' test]]
다음으로
except_clause: 'except' [test ['as' NAME]]
쉼표 토큰 대신 as를 사용하면 다음이
except (AttributeError, os.error):
예외 클래스의 튜플임을 명확히 이해할 수 있습니다. 이 새로운 구문은 Greg Ewing이 처음 제안했으며 [2] BDFL이 지지했습니다([2], [3]).
또한 as 다음 토큰을 test에서 NAME으로 제한하면 유효한 식별자만 except 대상으로 사용할 수 있습니다.
위 문법에서는 예외 클래스로 항상 괄호로 묶은 튜플이 필요하다는 점에 유의하십시오. 그렇게 하면 모호한 다음 구문이
except A, B:
Python 2.x와 3.x에서 서로 다른 의미를 가지므로 잡기 어려운 버그로 이어질 수 있지만, 3.x 코드에서는 합법적으로 나타날 수 없습니다.
의미 변경
관련 PEP 344와 관련된 가비지 컬렉션 문제를 해결하기 위해, Python 3의 except 문은 대상을 삭제하는 추가 바이트코드를 생성하여 참조 순환을 제거합니다. Phillip J. Eby [5]가 제안한 소스 간 변환은
try:
try_body
except E as N:
except_body
...
(Python 2.5 용어로) 다음과 같이 변환됩니다.
try:
try_body
except E, N:
try:
except_body
finally:
N = None
del N
...
구현은 이미 py3k(이전에는 “p3yk”라고 불림) 브랜치에 체크인되었습니다 [6].
호환성 문제
거의 모든 except 절을 변경해야 합니다. 식별자 대상을 사용하는 except 절은 다음에서 변경해야 합니다.
except E, N:
다음으로
except E as N:
튜플이 아니고 식별자도 아닌 대상을 사용하는 except 절(예: a.b.c[d])은 다음에서 변경해야 합니다.
except E, T:
다음으로
except E as t:
T = t
이 두 경우 모두 Guido van Rossum의 2to3 유틸리티 [7]에서 except 수정자 [8]를 사용하여 처리할 수 있습니다.
튜플 대상을 사용하는 except 절은 사례별로 수동 변환해야 합니다. 이러한 변경에는 대개 예외 클래스 자체의 변경도 수반되어야 합니다. 일반적으로 이러한 변경은 자동화할 수 없지만, 2to3 유틸리티는 except 절의 대상이 튜플인 경우를 알려 주므로 변환을 간소화할 수 있습니다.
except 절이 끝난 후에도 예외 인스턴스를 유지해야 하는 상황은 다음과 같이 쉽게 변환할 수 있습니다.
try:
...
except E as N:
...
...
다음과 같이 변경됩니다.
try:
...
except E as N:
n = N
...
...
이렇게 하면 블록 끝에서 N이 삭제될 때 n은 유지되므로 정상적으로 사용할 수 있습니다.
마지막으로 sys 모듈의 exc_type, exc_value 및 exc_traceback 특성을 사용하는 모든 코드를 제거해야 합니다. 이러한 특성은 각각 sys.exc_info()[0], sys.exc_info()[1] 및 sys.exc_info()[2]로 대체할 수 있으며, 이 변환은 2to3의 sysexcattrs 수정자로 수행할 수 있습니다.
2.6 - 3.0 호환성
Python 2.6과 3.0 간의 향후 호환성을 지원하기 위해 except ... as ...: 구문이 2.x 계열로 백포트됩니다. 따라서 문법은 다음에서 변경됩니다.:
except_clause: 'except' [test [',' test]]
다음으로:
except_clause: 'except' [test [('as' | ',') test]]
except 문의 절 끝 정리 의미론은 2.x 계열 릴리스에 포함되지 않습니다.
미해결 문제
“sys.exc_info()” 대체 또는 제거
sys.exc_info()를 제거하거나 sys.exception 특성 또는 sys.get_exception() 함수로 대체하자는 아이디어는 python-3000에서 여러 차례 제기되었으며 ([9], [10]), PEP 344의 “미해결 문제” 절에서도 언급되었습니다.
sys.exc_info() 호출과 일부 특성 접근을 대체하는 2to3 수정자를 작성하는 일은 간단하지만, 정적 분석으로 sys.exc_info()의 값을 인자로 받는 함수를 찾아 수정하는 일은 훨씬 더 어렵습니다. 마찬가지로 이는 sys.exc_info()를 기준으로 정의된 모든 API의 문서를 다시 작성해야 하는 문제도 해결하지 못합니다.
구현
이 PEP는 리비전 53342 [11] 및 53349 [12]에서 구현되었습니다. 2.6에서 새로운 except 구문을 지원하는 기능은 리비전 55446 [13]에서 구현되었습니다.
참고 자료
Copyright
This document has been placed in the public domain.