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

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

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] 객체의 사용법을 알고 싶습니다.



답변

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

>>> 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'

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


답변

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)


답변

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'


답변

예외 처리기에서 예외 개체 또는 역 추적 개체를 가져올 때주의해야합니다. 이로 인해 순환 참조 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()트레이스 백에 참여하는 모든 프레임은 노트북이 종료되거나 다른 예외가 이전에 저장된 백 트레이스를 덮어 쓸 때까지 해제되지 않습니다. 이것은 매우 문제가됩니다. 프레임을 청소하지 않고 트레이스 백을 저장해서는 안됩니다. 여기에 수정 사항이 제출 되었습니다 .


답변

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

except Exception as e:
    tb = sys.exc_info()
    print(e.with_traceback(tb[2]))


답변