traceback / sys.exc_info () 값을 변수에 저장하는 방법은 무엇입니까?


127

오류의 이름과 추적 정보를 변수에 저장하고 싶습니다. 여기 내 시도가 있습니다.

import sys
try:
    try:
        print x
    except Exception, ex:
        raise NameError
except Exception, er:
    print "0", sys.exc_info()[0]
    print "1", sys.exc_info()[1]
    print "2", sys.exc_info()[2]

산출:

0 <type 'exceptions.NameError'>
1 
2 <traceback object at 0xbd5fc8>

원하는 출력 :

0 NameError
1
2 Traceback (most recent call last):
  File "exception.py", line 6, in <module>
    raise NameError

추신 : 트레이스 백 모듈을 사용하여 쉽게 할 수 있다는 것을 알고 있지만 여기에서는 sys.exc_info () [2] 객체의 사용법을 알고 싶습니다.


sys.exc_info () [x] .__ str __ () 인쇄를 시도 했습니까?
zmbq 2011

3
프로그램에서 무슨 일이 일어나고 있는지 오해했을 수 있습니다. "sys.exc_info () [2] object"라고 부르는 것은 역 추적 개체의 인스턴스입니다 (= 당신은 역 추적 모듈을 이미 사용하고 있습니다). 이제 traceback 모듈의 도우미 함수를 사용하지 않고도 해당 개체를 조작 할 수 있지만, 여전히 사용하고 있다는 사실은 변경되지 않습니다. :)
mac

1
그래서 @mac 도우미 기능을 사용하거나 사용하지 않고이 개체의 값에 액세스하는 것을 도와주세요.
codersofthedark

1
@dragosrsupercool-아래 내 대답에서 언급했듯이 추적 문서를 봐야 합니다 . 텍스트로 데이터를 검색하는 방법에 대한 예제를 제공했지만 예외 이름, 코드 행 등을 추출 할 수있는 객체의 다른 메서드가 있습니다. 올바른 방법은 실제로 값 이후에 ...

1
다른 질문에 대한 나의 대답 은 링크를 통해 세부 사항을 설명하는 데 도움이 될 수 있습니다! 미리 준비된 문자열의 경우 표준 라이브러리 추적 모듈이 괜찮아 보입니다. 자세한 내용은 출처 ( <python install path>/Lib/traceback.py)에서 자세한 정보를 확인하세요.
pythonlarry 2013

답변:


180

이것이 내가하는 방법입니다.

>>> import traceback
>>> try:
...   int('k')
... except:
...   var = traceback.format_exc()
... 
>>> print var
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'

그러나 나중에 변수를 처리하려는 방법에 따라 더 적합한 방법을 찾을 수 있으므로 트레이스 백 문서를 살펴 봐야 합니다.


1
역 추적 모듈을 사용하지 않고 방법을 찾고있었습니다. 이 객체 참조에서 추적 정보를 인쇄 할 수있는 방법이 있습니까? sys.exc_info () [2]
codersofthedark

그렇기 때문에 sys.exc_info () [2] .format_exc ()와 같은 일을 할 수 있다고 생각했지만 작동하지 않습니다. 따라서 역 추적 객체 sys.exc_info ()에서 값을 어떻게 추출 할 수 있는지 궁금합니다. [2]. 어떤 생각?
codersofthedark

1
sys.exc_info () [2] .tb_text가 다음 오류를 제공합니다.-> AttributeError : 'traceback'개체에 'tb_text'속성이 없습니다
codersofthedark

4
@dragosrsupercool- sys.exc_info()[2].tb_frame.f_code.co_names[3],하지만 그건 말도 안 돼요 ... traceback표준 라이브러리에 호출 된 모듈이 있다면 그 이유가 있습니다 ... :)
mac

2
@codersofthedark가이 traceback.format_exception(*sys.exc_info())를 수행하는 방법입니다. 그러나 그것은 기능적으로 traceback.format_exc().
wizzwizz4

25

sys.exc_info ()는 세 가지 값 (유형, 값, 역 추적)이있는 튜플을 반환합니다.

  1. 여기서 type은 처리되는 Exception의 예외 유형을 가져옵니다.
  2. value는 예외 클래스의 생성자에 전달되는 인수입니다.
  3. traceback에는 예외가 발생한 위치 등과 같은 스택 정보가 포함됩니다.

예를 들어, 다음 프로그램에서

try:

    a = 1/0

except Exception,e:

    exc_tuple = sys.exc_info()

이제 튜플을 인쇄하면 값은 다음과 같습니다.

  1. exc_tuple [0] 값은 " ZeroDivisionError "가됩니다.
  2. exc_tuple [1] 값은 " 정수 나누기 또는 0으로 모듈로 "입니다 (예외 클래스에 매개 변수로 전달 된 문자열).
  3. exc_tuple [2] 값은 " (일부 메모리 주소)의 트랙백 객체 "가됩니다.

위의 세부 사항은 단순히 예외를 문자열 형식으로 인쇄하여 가져올 수도 있습니다.

print str(e)

Python3의 경우 exc_tuple [1] (일명 값)은 "매개 변수로 전달 된 문자열"이 아니라 예외 의 인스턴스 입니다. 참조 : docs.python.org/3/library/sys.html#sys.exc_info
Shi

"예외를 e :로 제외"해야하지 않습니까?
Henrik

20

traceback.extract_stack()모듈 및 기능 이름과 줄 번호에 편리하게 액세스하려는 경우 사용 합니다.

출력 ''.join(traceback.format_stack())과 같은 문자열을 원하는 경우 사용하십시오 traceback.print_stack().

심지어와 공지 사항 ''.join()당신의 요소 때문에, 여러 줄 문자열을 얻을 것이다 format_stack()포함 \n. 아래 출력을 참조하십시오.

을 기억하십시오 import traceback.

다음은 traceback.extract_stack(). 가독성을 위해 서식이 추가되었습니다.

>>> traceback.extract_stack()
[
   ('<string>', 1, '<module>', None),
   ('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
   ('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
   ('<pyshell#1>', 1, '<module>', None)
]

다음은 ''.join(traceback.format_stack()). 가독성을 위해 서식이 추가되었습니다.

>>> ''.join(traceback.format_stack())
'  File "<string>", line 1, in <module>\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
       ret = method(*args, **kwargs)\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
       exec(code, self.locals)\n  File "<pyshell#2>", line 1, in <module>\n'

4

예외 처리기에서 예외 개체 또는 역 추적 개체를 가져올 때주의해야합니다. 이로 인해 순환 참조 gc.collect()가 발생하고 수집에 실패하기 때문입니다. 이것은 역 추적 객체가 적시에 지워지지 않고 gc.collect()in finally섹션에 대한 명시적인 호출조차 아무것도 하지 않는 ipython / jupyter 노트북 환경에서 특정 문제인 것으로 보입니다 . 그리고 그로 인해 메모리를 회수하지 못하는 거대한 객체가 있다면 그것은 큰 문제입니다 (예를 들어,이 솔루션이없는 CUDA 메모리 부족 예외는 복구를 위해 완전한 커널 재시작을 필요로 함).

일반적으로 역 추적 객체를 저장하려면 다음 locals()과 같이에 대한 참조에서이를 지워야합니다 .

import sys, traceback, gc
type, val, tb = None, None, None
try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
    raise type(val).with_traceback(tb)

jupyter 노트북의 경우 최소한 예외 핸들러 내에서이를 수행해야합니다.

try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
    raise type(val).with_traceback(tb)
finally:
    # cleanup code in here
    gc.collect()

Python 3.7로 테스트되었습니다.

추신 ipython 또는 jupyter 노트북 환경의 문제 %tb는 추적을 저장하고 나중에 언제든지 사용할 수 있도록 만드는 마법 이 있다는 것 입니다. 결과적으로 locals()트레이스 백에 참여하는 모든 프레임은 노트북이 종료되거나 다른 예외가 이전에 저장된 백 트레이스를 덮어 쓸 때까지 해제되지 않습니다. 이것은 매우 문제가됩니다. 프레임을 청소하지 않고 트레이스 백을 저장해서는 안됩니다. 여기에 수정 사항이 제출 되었습니다 .


3

이 개체는 Exception.with_traceback()함수 에서 매개 변수로 사용할 수 있습니다 .

except Exception as e:
    tb = sys.exc_info()
    print(e.with_traceback(tb[2]))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.