파이썬은 "모금"사용법


197

파이썬 raiseraise from파이썬 의 차이점은 무엇입니까 ?

try:
    raise ValueError
except Exception as e:
    raise IndexError

생산량

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError
IndexError

try:
    raise ValueError
except Exception as e:
    raise IndexError from e

생산량

Traceback (most recent call last):
  File "tmp.py", line 2, in <module>
    raise ValueError
ValueError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "tmp.py", line 4, in <module>
    raise IndexError from e
IndexError

9
PEP-3134 를 읽었 습니까?
jonrsharpe

4
이제 사용하십시오 raise IndexError from None.
Martijn Pieters

11
허. raise IndexError from FalseTypeError아닌을 발생 IndexError시킵니다. 내 하루를 보냈습니다.
Mad Physicist


이것이 올바른 장소인지 확실하지 않지만 Spyder를 사용하는 사람에게는이 전체 구성이 작동하지 않습니다. 현재 3 년 이상 문제 ( github.com/spyder-ide/spyder/issues/2943 )가되었지만 체인 된 예외가 필요하지 않은 것으로 보입니다.
Emil Bode

답변:


230

차이점은 사용하는 경우이다 from__cause__속성이 설정되어 있고 메시지는 예외가되었다는 내용 을 직접 발생 . 생략하면 fromno __cause__가 설정되지만 __context__속성 도 설정 될 수 있으며 추적은 다른 상황을 처리 하는 동안 컨텍스트를 표시합니다 .

예외 처리기에서 __context__사용한 경우 발생 설정 raise; raise다른 곳에서 사용 하면 no __context__도 설정됩니다.

a __cause__가 설정되면 __suppress_context__ = True예외에서도 플래그가 설정됩니다. 경우 __suppress_context__에 설정 True의는 __context__역 추적을 인쇄 할 때 무시됩니다.

컨텍스트를 표시 하지 않으려 는 예외 핸들러 ( 다른 예외 발생 메시지를 처리 하는 동안 원하지 않음 )에서 발생하는 경우을 사용 raise ... from None하여로 설정 __suppress_context__하십시오 True.

다시 말해, 파이썬은 예외에 대한 컨텍스트 를 설정 하므로 예외가 발생한 위치를 조사하여 다른 예외가 대체되었는지 확인할 수 있습니다. 또한 예외에 원인 을 추가 하여 다른 예외에 대해 트레이스 백을 명시 적으로 만들 수 있으며 (다른 표현 사용) 컨텍스트는 무시되지만 디버깅 할 때 여전히 검사 할 수 있습니다. 사용 raise ... from None하면 인쇄중인 컨텍스트를 억제 할 수 있습니다.

raise진술 문서를 참조하십시오 :

from절은 예외 체인에 사용됩니다. 제공되는 경우 두 번째 표현식 은 또 다른 예외 클래스 또는 인스턴스 여야하며, __cause__속성 으로 작성된 예외에 첨부됩니다 (쓰기 가능). 발생한 예외가 처리되지 않으면 두 가지 예외가 모두 인쇄됩니다.

>>> try:
...     print(1 / 0)
... except Exception as exc:
...     raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

예외 처리기 또는 finally절 에서 예외가 발생하면 유사한 메커니즘이 암시 적으로 작동합니다 . 그런 다음 이전 예외가 새 예외의 __context__특성 으로 첨부됩니다 .

>>> try:
...     print(1 / 0)
... except:
...     raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened

또한 컨텍스트에 대한 자세한 내용과 예외에 첨부 된 정보 는 내장 예외 문서 를 참조하십시오.


11
명시 적으로 사용하여 예외 체인 어떤 이유가 있습니까 from__cause__암시 대신은 __context__? 어떤 예외가 다른 예외를 첨부하는 경우가 except있습니까?
darkfeline

13
@darkfeline : 데이터베이스 API가 웹 및 디스크를 포함한 다양한 소스에서 데이터베이스 열기를 지원한다고 가정합니다. 귀하의 API는 것입니다 항상 인상 DatabaseError데이터베이스를 여는 실패하는 경우. 그러나 IOError파일을 열지 못했거나 HTTPErrorURL이 작동하지 않아서 실패한 경우에는 API를 사용하는 개발자가 이유를 디버깅 할 수 있도록 명시 적으로 포함하려는 컨텍스트입니다. 그 순간에을 사용 raise DatabaseError from original_exception합니다.
Martijn Pieters

4
@darkfeline : 그 개발자가 자신의 API의 데이터베이스 API의 사용을 포장하고 전달하고 싶었다 경우 IOErrorHTTPError에게 그들의 소비자, 그들은 사용해야 할 것입니다 raise NewException from databaseexception.__cause__지금과는 다른 예외를 사용하여, DatabaseException그들은 단지 잡은.
Martijn Pieters

2
@ dan3 : 아니오, 없습니다. 예외 체인은 순수하게 Python 3 기능입니다.
Martijn Pieters

5
@ laike9m : 예외를 처리 할 때 새로운 예외 foo를 제기하고 싶 습니까? 그런 다음 Python 상태를 직접 사용 하여 사용할 수 있습니다 . 당신이 경우 하지 않습니다 사용 후, 파이썬은 여전히 모두를 인쇄 할 수 있지만, 상태 것으로 취급 중에 , 제기되었다 , 다른 메시지는 플래그에 오류 처리에 가능한 버그 의도. barraise bar from foofoo barfrom foofoobar
Martijn Pieters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.