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

Python 개선 제안 한국어 번역

PEP 3109 – Python 3000에서의 예외 발생

Author:
Collin Winter <collinwinter at google.com>
Status:
Final
Type:
Standards Track
Created:
19-Jan-2006
Python-Version:
3.0
Post-History:


Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 코드 잡음과 언어의 크기를 모두 줄이기 위해 Python의 예외 발생 메커니즘을 변경합니다.

근거

Python의 지침이 되는 격언 중 하나는 “명백한 방법이 하나 – 되도록이면 단 하나만 – 있어야 합니다”입니다. Python 2.x의 raise 문은 같은 생각을 여러 방식으로 표현할 수 있게 허용하므로 이 원칙을 위반합니다. 예를 들어, 다음 문들은 서로 동등합니다:

raise E, V

raise E(V)

raise 문에는 예외에 임의의 트레이스백을 첨부할 수 있는 세 번째 형태도 있습니다 [1]:

raise E, V, T

여기서 T는 트레이스백입니다. PEP 344에 명시된 대로, Python 3.x의 예외 객체는 __traceback__ 속성을 가지게 되므로, 세 개의 표현식을 받는 raise 문을 다음과 같이 변환할 수 있습니다:

raise E, V, T

다음과 같이 변환됩니다

e = E(V)
e.__traceback__ = T
raise e

이러한 변환을 사용하면 raise 문의 형태를 네 가지에서 두 가지로 줄일 수 있습니다:

  1. raise (인자 없음)는 except 스위트 안에서 활성 예외를 다시 발생시키는 데 사용됩니다.
  2. raise EXCEPTION은 새 예외를 발생시키는 데 사용됩니다. 이 형태에는 두 가지 하위 변형이 있습니다: EXCEPTION은 예외 클래스이거나 예외 클래스의 인스턴스일 수 있으며, 유효한 예외 클래스는 BaseException과 그 서브클래스입니다(PEP 352). EXCEPTION이 서브클래스이면, 예외 인스턴스를 얻기 위해 인자 없이 호출됩니다.

    그 밖의 것을 발생시키는 것은 오류입니다.

이 통합을 통해 얻을 수 있는 더 실질적인 이점이 하나 더 있는데, 이는 A.M. Kuchling이 지적한 바와 같습니다 [2].

PEP 8 doesn't express any preference between the
two forms of raise statements:
raise ValueError, 'blah'
raise ValueError("blah")

I like the second form better, because if the exception arguments
are long or include string formatting, you don't need to use line
continuation characters because of the containing parens.

BDFL도 이에 동의했으며 [3] 여러 raise 형태의 통합을 지지했습니다.

문법 변경

Python 3에서 raise 문의 문법은 다음에서 [1]

raise_stmt: 'raise' [test [',' test [',' test]]]

다음으로 바뀝니다

raise_stmt: 'raise' [test]

내장 타입의 변경

예외 발생과 관련이 있으므로, 제너레이터 객체의 throw() 메서드 시그니처도 바뀌어 선택적인 두 번째와 세 번째 매개변수가 제거됩니다. 따라서 시그니처는 (PEP 342) 다음에서

generator.throw(E, [V, [T]])

다음으로 바뀝니다

generator.throw(EXCEPTION)

여기서 EXCEPTION은 BaseException의 서브클래스이거나 BaseException 서브클래스의 인스턴스입니다.

의미 변경

Python 2에서는 다음 raise 문이 유효합니다

raise ((E1, (E2, E3)), E4), V

인터프리터는 튜플의 첫 번째 요소를 (재귀적으로) 예외 타입으로 취하므로, 위의 문은 다음과 완전히 동등합니다

raise E1, V

Python 3.0부터는 이와 같이 튜플을 발생시키는 기능이 더 이상 지원되지 않습니다. 이 변경으로 raise 문은 제너레이터 객체의 throw() 메서드와 일관되게 됩니다. 이 메서드는 이미 이러한 사용을 허용하지 않습니다.

호환성 문제

식이 두 개 또는 세 개인 모든 raise 문을 수정해야 하며, 제너레이터에 대해 식이 두 개 또는 세 개인 모든 throw() 호출도 수정해야 합니다. 다행히 이 경우 Python 2.x에서 Python 3.x로 옮기는 작업은 간단합니다. Guido van Rossum의 2to3 유틸리티 [4]에서 raise 및 throw 픽서 ([5], [6])를 사용하면 기계적으로 처리할 수 있습니다.

다음과 같은 변환이 수행됩니다:

  1. 식이 없거나 하나인 raise 문은 그대로 유지됩니다.
  2. 식이 두 개인 raise 문은 다음 형태에서
    raise E, V
    

    다음 형태로 변환됩니다.

    raise E(V)
    

    식이 두 개인 throw() 호출은 다음 형태에서

    generator.throw(E, V)
    

    다음 형태로 변환됩니다.

    generator.throw(E(V))
    

    이 변환에 관한 주의 사항은 5번 항목을 참고하십시오.

  3. 식이 세 개인 raise 문은 다음 형태에서
    raise E, V, T
    

    다음 형태로 변환됩니다.

    e = E(V)
    e.__traceback__ = T
    raise e
    

    식이 세 개인 throw() 호출은 다음 형태에서

    generator.throw(E, V, T)
    

    다음 형태로 변환됩니다.

    e = E(V)
    e.__traceback__ = T
    generator.throw(e)
    

    이 변환에 관한 주의 사항은 5번 항목을 참고하십시오.

  4. E가 튜플 리터럴이고 식이 두 개 또는 세 개인 raise 문은 2to3의 raise 픽서를 사용하여 자동으로 변환할 수 있습니다. 함수 호출의 결과처럼 E가 리터럴이 아닌 튜플인 raise 문은 수동으로 변환해야 합니다.
  5. E가 예외 클래스이고 V가 예외 인스턴스이며 식이 두 개 또는 세 개인 raise 문은 특별히 주의해야 합니다. 이러한 경우는 두 부류로 나뉩니다:
    1. 인자가 없는 raise 문을 길게 풀어 쓴 형태로 사용하는 raise E, V 예를 들어, F가 E의 서브클래스라고 가정하면
      try:
          something()
      except F as V:
          raise F(V)
      except E as V:
          handle(V)
      

      이는 다음과 같이 표현하는 것이 더 좋습니다.

      try:
          something()
      except F:
          raise
      except E as V:
          handle(V)
      
    2. 예외를 다른 클래스로 “캐스팅”하는 방법으로 사용하는 raise E, V distutils.compiler.unixcompiler의 예를 들면
      try:
          self.spawn(pp_args)
      except DistutilsExecError as msg:
          raise CompileError(msg)
      

      이는 다음과 같이 표현하는 것이 더 좋습니다.

      try:
          self.spawn(pp_args)
      except DistutilsExecError as msg:
          raise CompileError from msg
      

      PEP 344에서 도입된 raise ... from ... 문법을 사용합니다.

구현

이 PEP는 리비전 57783 [7]에서 구현되었습니다.

참고 문헌