Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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:


Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 Python 3.0에서 Python 문법의 모호성을 없애고, 예외 클래스를 단순화하고, 예외의 가비지 컬렉션을 단순화하며, 언어의 크기를 줄이는 데 도움이 되는 변경 사항을 소개합니다.

근거

  1. Python 2.x의 except 절에는 파서가 다음 코드를 어떻게 해석해야 할지 구별할 수 없는 구문상의 모호성이 있습니다.
    except <expression>, <expression>:
    

    이 코드를 다음과 같이 해석해야 하는지,

    except <type>, <type>:
    

    아니면 다음과 같이 해석해야 하는지 구별할 수 없습니다.

    except <type>, <name>:
    

    Python 2는 후자의 의미를 택하며, 그 대가로 전자는 다음과 같이 괄호로 묶어야 합니다.

    except (<type>, <type>):
    
  2. PEP 352에 명시된 대로 예외를 튜플로 취급하는 기능이 제거될 것이며, 따라서 다음 코드는 더 이상 동작하지 않습니다.
    except os.error, (errno, errstr):
    

    자동 언패킹이 더 이상 불가능해지므로, 튜플을 except 대상으로 사용하는 기능을 제거하는 것이 바람직합니다.

  3. PEP 344에 명시된 대로, Python 3의 예외 인스턴스는 __traceback__ 속성을 가지게 됩니다. 해당 PEP의 미해결 문제(Open Issues) 절에는 이 속성 때문에 생기는 가비지 컬렉션 문제를 다루는 단락이 있습니다. 이 문제는 “예외 -> 트레이스백 -> 스택 프레임 -> 예외”로 이어지는 참조 순환입니다. 이 순환 때문에 다음 GC 실행 때까지 모든 지역 변수가 스코프에 남아 있게 됩니다. 이 PEP는 Python 3의 except 절에 정리(cleanup) 의미를 추가하여 이 문제를 해결하고자 하며, 이에 따라 except 스위트가 끝날 때 대상 이름이 삭제됩니다.
  4. “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:

튜플도 식별자도 아닌 대상(예: a.b.c[d])을 가진 except 절은 다음 형태에서

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]에서 구현되었습니다.

참고 문헌