例外の説明とスタックトレースを取得します。
-
14-10-2019 - |
質問
Pythonのスタックトレースと例外に関する多くの投稿を見てきました。しかし、私が必要なものを見つけていません。
例外を提起する可能性のあるPython 2.7コードのチャンクがあります。私はそれを捕まえて、 ストリング その完全な説明とエラーを引き起こしたスタックトレース(単にコンソールで表示するために使用するすべて)。 GUIのテキストボックスに印刷するには、この文字列が必要です。
このようなもの:
try:
method_that_can_raise_an_exception(params)
except Exception as e:
print_to_textbox(complete_exception_description(e))
問題は: 関数は何ですか complete_exception_description
?
解決
を参照してください traceback
モジュール、特に format_exc()
働き。 ここ.
import traceback
try:
raise ValueError
except ValueError:
tb = traceback.format_exc()
else:
tb = "No error"
finally:
print tb
他のヒント
完全なスタックトレースを取得することを実証するために、きちんと複雑なスタックトレースを作成しましょう。
def raise_error():
raise RuntimeError('something bad happened!')
def do_something_that_might_error():
raise_error()
フルスタックトレースのログ
ベストプラクティスは、モジュール用にロガーをセットアップすることです。モジュールの名前を知っており、レベルを変更できる(ハンドラーなどの属性の中でも)
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
そして、このロガーを使用してエラーを取得できます。
try:
do_something_that_might_error()
except Exception as error:
logger.exception(error)
どのログ:
ERROR:__main__:something bad happened!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
そのため、エラーが発生したときと同じ出力を取得します。
>>> do_something_that_might_error()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
文字列だけを取得します
本当に文字列が必要な場合は、 traceback.format_exc
代わりに機能し、ここで文字列のログを表示します:
import traceback
try:
do_something_that_might_error()
except Exception as error:
just_the_string = traceback.format_exc()
logger.debug(just_the_string)
どのログ:
DEBUG:__main__:Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
>>> import sys
>>> import traceback
>>> try:
... 5 / 0
... except ZeroDivisionError as e:
... type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
[' File "<stdin>", line 2, in <module>\n']
>>> value_
ZeroDivisionError('integer division or modulo by zero',)
>>> type_
<type 'exceptions.ZeroDivisionError'>
>>>
>>> 5 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
あなたが使う sys.exc_info() 情報と関数を収集します traceback
フォーマットするモジュール。ここ フォーマットの例です。
例外文字列全体は次のとおりです。
>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
['Traceback (most recent call last):\n', ' File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: integer division or modulo by zero\n']
Python 3を使用すると、次のコードがフォーマットします Exception
使用して取得されるように正確にオブジェクト traceback.format_exc()
:
import traceback
try:
method_that_can_raise_an_exception(params)
except Exception as ex:
print(''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))
利点は、それだけです Exception
オブジェクトが必要です(記録されたおかげで __traceback__
属性)、したがって、さらなる処理のために別の関数への引数としてより簡単に渡すことができます。
使用している人のために Python-3
使用 traceback
モジュールと exception.__traceback__
次のように、スタックトレースを抽出できます。
- をつかみます 現在 使用したスタックトレース
traceback.extract_stack()
- 最後の3つの要素を削除します(それらはスタック内のエントリであるため、デバッグ機能に到達しました)
- 追加します
__traceback__
使用している例外オブジェクトからtraceback.extract_tb()
- 全体を使用してフォーマットします
traceback.format_list()
import traceback
def exception_to_string(excp):
stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__) # add limit=??
pretty = traceback.format_list(stack)
return ''.join(pretty) + '\n {} {}'.format(excp.__class__,excp)
簡単なデモンストレーション:
def foo():
try:
something_invalid()
except Exception as e:
print(exception_to_string(e))
def bar():
return foo()
電話をかけると、次の出力が得られます bar()
:
File "./test.py", line 57, in <module>
bar()
File "./test.py", line 55, in bar
return foo()
File "./test.py", line 50, in foo
something_invalid()
<class 'NameError'> name 'something_invalid' is not defined
また、組み込みのPythonモジュールの使用を検討することもできます。 CGITB, 、ローカル変数の値、ソースコードコンテキスト、関数パラメーターなどを含む、いくつかの非常に優れた、適切にフォーマットされた例外情報を取得するには。
たとえば、このコードの場合...
import cgitb
cgitb.enable(format='text')
def func2(a, divisor):
return a / divisor
def func1(a, b):
c = b - 5
return func2(a, c)
func1(1, 5)
この例外出力を取得します...
ZeroDivisionError
Python 3.4.2: C:\tools\python\python.exe
Tue Sep 22 15:29:33 2015
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
c:\TEMP\cgittest2.py in <module>()
7 def func1(a, b):
8 c = b - 5
9 return func2(a, c)
10
11 func1(1, 5)
func1 = <function func1>
c:\TEMP\cgittest2.py in func1(a=1, b=5)
7 def func1(a, b):
8 c = b - 5
9 return func2(a, c)
10
11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0
c:\TEMP\cgittest2.py in func2(a=1, divisor=0)
3
4 def func2(a, divisor):
5 return a / divisor
6
7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
__cause__ = None
__class__ = <class 'ZeroDivisionError'>
__context__ = None
__delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
__dict__ = {}
__dir__ = <built-in method __dir__ of ZeroDivisionError object>
__doc__ = 'Second argument to a division or modulo operation was zero.'
__eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
__format__ = <built-in method __format__ of ZeroDivisionError object>
__ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
__getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
__gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
__hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
__init__ = <method-wrapper '__init__' of ZeroDivisionError object>
__le__ = <method-wrapper '__le__' of ZeroDivisionError object>
__lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
__ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
__new__ = <built-in method __new__ of type object>
__reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
__reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
__repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
__setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
__setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
__sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
__str__ = <method-wrapper '__str__' of ZeroDivisionError object>
__subclasshook__ = <built-in method __subclasshook__ of type object>
__suppress_context__ = False
__traceback__ = <traceback object>
args = ('division by zero',)
with_traceback = <built-in method with_traceback of ZeroDivisionError object>
The above is a description of an error in a Python program. Here is
the original traceback:
Traceback (most recent call last):
File "cgittest2.py", line 11, in <module>
func1(1, 5)
File "cgittest2.py", line 9, in func1
return func2(a, c)
File "cgittest2.py", line 5, in func2
return a / divisor
ZeroDivisionError: division by zero
例外が処理されていないときに与えられた同じ情報を取得したい場合は、このようなことをすることができます。行う import traceback
その後:
try:
...
except Exception as e:
print(traceback.print_tb(e.__traceback__))
Python 3.7を使用しています。
私の2セント:
import sys, traceback
try:
...
except Exception, e:
T, V, TB = sys.exc_info()
print ''.join(traceback.format_exception(T,V,TB))
次のヘルパークラスを定義しました。
import traceback
class TracedExeptions(object):
def __init__(self):
pass
def __enter__(self):
pass
def __exit__(self, etype, value, tb):
if value :
if not hasattr(value, 'traceString'):
value.traceString = "\n".join(traceback.format_exception(etype, value, tb))
return False
return True
後でこのように使用できます:
with TracedExeptions():
#some-code-which-might-throw-any-exception
そして後でこのように消費することができます:
def log_err(ex):
if hasattr(ex, 'traceString'):
print("ERROR:{}".format(ex.traceString));
else:
print("ERROR:{}".format(ex));
(背景:私は使用していたためにイライラしました Promise
一緒にs Exception
S、残念ながら、ある場所で提起された例外を別の場所でOn_rejected Handlerに渡すため、元の場所からトレースバックを取得することは困難です)