programing

예외 개체에서 추적 정보 추출

css3 2023. 6. 29. 20:18

예외 개체에서 추적 정보 추출

출처를 알 수 없는 예외 개체가 주어졌을 때 추적을 얻을 수 있는 방법이 있습니까?다음과 같은 코드가 있습니다.

def stuff():
   try:
       .....
       return useful
   except Exception as e:
       return e

result = stuff()
if isinstance(result, Exception):
    result.traceback <-- How?

예외 개체가 있는 경우 추적을 다시 추출하려면 어떻게 해야 합니까?

이 질문에 대한 답은 사용 중인 Python 버전에 따라 다릅니다.

파이썬 3에서

에는 순니다가 포함되어 . 예외는 다음과 같이 제공됩니다.__traceback__추적백을 포함하는 특성입니다.이 하며 이속은쓰가다사음편수설있다니습정리게할하용을 할 수 .with_traceback: 예외 방법:

raise Exception("foo occurred").with_traceback(tracebackobj)

이러한 기능은 설명서의 일부로 최소한 설명되어 있습니다.

답변의 이 부분에 대한 모든 공은 이 정보를 처음 게시한 Victor에게 돌아가야 합니다.이 답변이 맨 위에 고정되어 있고, 파이썬 3이 점점 일반화되고 있기 때문에 여기에 포함하는 것입니다.

파이썬 2에서

짜증날 정도로 복잡합니다.트레이스백의 문제는 스택 프레임에 대한 참조가 있고 스택 프레임에 대한 참조가 있는 트레이스백에 대한 참조가 있다는 것입니다.당신은 이해합니다.이로 인해 가비지 수집기에 문제가 발생합니다.(먼저 이 점을 지적해주신 ecatmur님께 감사드립니다.)

이 문제를 해결하는 좋은 방법은 수술을 받은주기를 깨는 것입니다.exceptPython 3이 수행하는 작업인 절입니다.Python 2 솔루션은 훨씬 더 추합니다. 당신은 내부에서만 작동하는 애드혹 sys.exc_info()기능을 제공받습니다. except . 예외, 예외 유형 및 현재 처리 중인 예외에 대한 추적을 포함하는 튜플을 반환합니다.

그래서 만약 당신이 안에 있다면.except절, 당은출사수있다의 할 수 .sys.exc_info()모듈과 함께 다양한 유용한 작업을 수행합니다.

>>> import sys, traceback
>>> def raise_exception():
...     try:
...         raise Exception
...     except Exception:
...         ex_type, ex, tb = sys.exc_info()
...         traceback.print_tb(tb)
...     finally:
...         del tb
... 
>>> raise_exception()
  File "<stdin>", line 3, in raise_exception

그러나 편집한 내용에서 알 수 있듯이 예외가 이미 처리된 후 처리되지 않았다면 인쇄되었을 추적을 다시 가져오려고 합니다.그것은 훨씬 더 어려운 질문입니다.불행하게도,sys.exc_info아온다를 합니다.(None, None, None)예외가 처리되지 않을 때기타관련sys속성도 도움이 되지 않습니다. sys.exc_traceback되지 않을 는 더 되지 않으며 되지 않습니다. 이 경우는 사용되지 않습니다.sys.last_traceback완벽한 것처럼 보이지만 대화형 세션 중에만 정의된 것으로 보입니다.

예외 발생 방법을 제어할 수 있는 경우 및 사용자 지정 예외를 사용하여 일부 정보를 저장할 수 있습니다.하지만 저는 그것이 어떻게 작동할지 완전히 확신할 수는 없습니다.

사실, 예외를 잡고 반환하는 것은 일종의 특이한 일입니다.어쨌든 이것은 당신이 리팩터링이 필요하다는 신호일 수 있습니다.

Python 3.0[PEP 3109] 이후로 기본 제공 클래스는__traceback__를 포함하는 속성traceback object(Python 3.2.3 사용):

>>> try:
...     raise Exception()
... except Exception as e:
...     tb = e.__traceback__
...
>>> tb
<traceback object at 0x00000000022A9208>

문제는 한동안 구글링을 해본 결과 몇 개의 기사만 발견했을 뿐 사용해야 하는지 또는 사용하지 말아야 하는지에 대한 설명이 하나도 없다는 것입니다.__traceback__.

그러나 Python 3 설명서에는 다음과 같이 나와 있습니다.

트레이스백 개체는 일반적으로 예외가 발생하여 해당 개체에 다음과 같이 연결될 때 자동으로 생성됩니다.__traceback__쓰기 가능한 특성입니다.

그래서 저는 그것이 사용되어야 한다고 생각합니다.

Python 3의 예외 개체에서 문자열로 추적을 가져오는 방법:

import traceback

# `e` is an exception object that you get from somewhere
traceback_str = ''.join(traceback.format_tb(e.__traceback__))

traceback.format_tb(...) 문자열 목록을 반환합니다. ''.join(...)그들을 하나로 묶습니다.

또한 단말기에 인쇄된 전체 추적을 실제로 되돌리려면 다음과 같이 해야 합니다.

>>> try:
...     print(1/0)
... except Exception as e:
...     exc = e
...
>>> exc
ZeroDivisionError('division by zero')
>>> tb_str = traceback.format_exception(etype=type(exc), value=exc, tb=exc.__traceback__)
>>> tb_str
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: division by zero\n']
>>> print("".join(tb_str))
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

사용하는 경우format_tb위의 답변에서 알 수 있듯이 더 적은 정보를 얻을 수 있습니다.

>>> tb_str = "".join(traceback.format_tb(exc.__traceback__))
>>> print("".join(tb_str))
  File "<stdin>", line 2, in <module>

당신은 어떤 것이 반환하는지 사용할 수 있습니다.str

아니면 stdout에 인쇄합니다.

import traceback

try:
    b"x81".decode()
except UnicodeError:
    traceback.print_exc() # prints to stdout
    my_traceback = traceback.format_exc() # returns a str
print(my_traceback)

실제 예외에서 가져와야 하는 경우(이유는 알 수 없지만)

traceback.format_exception 를 반환합니다.str

traceback.print_exception 표준 출력으로 인쇄

import traceback

try:
    b"x81".decode()
except UnicodeError as exc:
    # etype is inferred from `value` since python3.5 so no need to pass a value...
    # format_exception returns a list
    my_traceback = "".join(traceback.format_exception(etype=None, value=exc, tb=exc.__traceback__))
    traceback.print_exception(etype=None, value=exc, tb=exc.__traceback__)

주의.

다음에 대한 참조 저장 안 함__traceback__(또는)exc트레이스백 개체에는 콜 스택을 구성하는 모든 스택 프레임 개체에 대한 참조가 포함되어 있으며 각 스택 프레임에는 모든 로컬 변수에 대한 참조가 포함되어 있으므로 나중에 사용할 수 있습니다.따라서 추적백 개체에서 도달할 수 있는 개체의 전이적 폐쇄의 크기는 매우 클 수 있습니다.또한 해당 참조를 유지하는 경우 이러한 개체는 가비지 수집되지 않습니다.메모리에 단기적으로 저장할 수 있도록 트레이스백을 다른 형태로 렌더링하는 것을 선호합니다."

Robert Smallshire - Python Beyond the Basics - 11 - 예외 및 오류 - 추적 개체

트레이스백이 예외에 저장되지 않는 데는 매우 타당한 이유가 있습니다. 트레이스백은 스택의 로컬에 대한 참조를 보유하기 때문에 순환 참조가 발생하고 순환 GC가 시작될 때까지 (일시적인) 메모리 누수가 발생합니다. (이것이 트레이스를 로컬 변수에 다시 저장해서는 안 되는 이유입니다.)

할 수 패치를 하는 입니다.stuff될 때 것 같은 느낌이 들킬 것 같아요.Exception실제로 특수 유형을 포착하고 있으며 예외가 발신자로 전파됩니다.

module_containing_stuff.Exception = type("BogusException", (Exception,), {})
try:
    stuff()
except Exception:
    import sys
    print sys.exc_info()

언급URL : https://stackoverflow.com/questions/11414894/extract-traceback-info-from-an-exception-object