Programming

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

procodes 2020. 8. 5. 21:30
반응형

변수에 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 ()는 세 가지 값 (type, value, traceback)을 가진 튜플을 반환합니다.

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

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

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().

Notice that even with ''.join() you will get a multi-line string, since the elements of format_stack() contain \n. See output below.

Remember to import traceback.

Here's the output from traceback.extract_stack(). Formatting added for readability.

>>> 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)
]

Here's the output from ''.join(traceback.format_stack()). Formatting added for readability.

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

Be careful when you take the exception object or the traceback object out of the exception handler, since this causes circular references and gc.collect() will fail to collect. This appears to be of a particular problem in the ipython/jupyter notebook environment where the traceback object doesn't get cleared at the right time and even an explicit call to gc.collect() in finally section does nothing. And that's a huge problem if you have some huge objects that don't get their memory reclaimed because of that (e.g. CUDA out of memory exceptions that w/o this solution require a complete kernel restart to recover).

In general if you want to save the traceback object, you need to clear it from references to locals(), like so:

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)

In the case of jupyter notebook, you have to do that at the very least inside the exception handler:

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()

Tested with python 3.7.

p.s. the problem with ipython or jupyter notebook env is that it has %tb magic which saves the traceback and makes it available at any point later. And as a result any locals() in all frames participating in the traceback will not be freed until the notebook exits or another exception will overwrite the previously stored backtrace. This is very problematic. It should not store the traceback w/o cleaning its frames. Fix submitted here.


The object can be used as a parameter in Exception.with_traceback() function:

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

참고URL : https://stackoverflow.com/questions/8238360/how-to-save-traceback-sys-exc-info-values-in-a-variable

반응형