blu*_*ish 376 python exception-handling stack-trace python-2.7
我在Python中看到了很多关于堆栈跟踪和异常的帖子.但还没找到我需要的东西.
我有一大堆Python 2.7代码可能引发异常.我想抓住它并将一个字符串分配给它的完整描述和导致错误的堆栈跟踪(我们只是在控制台上看到的所有内容).我需要这个字符串将其打印到GUI中的文本框.
像这样的东西:
try:
method_that_can_raise_an_exception(params)
except Exception as e:
print_to_textbox(complete_exception_description(e))
Run Code Online (Sandbox Code Playgroud)
问题是:功能是什么complete_exception_description
?
kin*_*all 552
查看traceback
模块,特别是format_exc()
功能.在这里.
import traceback
try:
raise ValueError
except ValueError:
tb = traceback.format_exc()
else:
tb = "No error"
finally:
print tb
Run Code Online (Sandbox Code Playgroud)
Aar*_*all 62
获取导致异常的异常描述和堆栈跟踪,全部作为字符串
要创建一个相当复杂的堆栈跟踪来演示我们获得完整的堆栈跟踪:
def raise_error():
raise RuntimeError('something bad happened!')
def do_something_that_might_error():
raise_error()
Run Code Online (Sandbox Code Playgroud)
最佳做法是为模块设置记录器.它将知道模块的名称并能够更改级别(以及其他属性,例如处理程序)
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
Run Code Online (Sandbox Code Playgroud)
我们可以使用此记录器来获取错误:
try:
do_something_that_might_error()
except Exception as error:
logger.exception(error)
Run Code Online (Sandbox Code Playgroud)
哪些日志:
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!
Run Code Online (Sandbox Code Playgroud)
所以我们得到的输出与出错时的输出相同:
>>> 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!
Run Code Online (Sandbox Code Playgroud)
如果你真的只想要字符串,请改用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)
Run Code Online (Sandbox Code Playgroud)
哪些日志:
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!
Run Code Online (Sandbox Code Playgroud)
aet*_*ter 34
>>> 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
Run Code Online (Sandbox Code Playgroud)
您可以使用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']
Run Code Online (Sandbox Code Playgroud)
Erw*_*yer 33
使用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__)))
Run Code Online (Sandbox Code Playgroud)
优点是只Exception
需要对象(由于记录的__traceback__
属性),因此可以更容易地作为参数传递给另一个函数以进行进一步处理.
don*_*hos 20
对于Python 3.5+:
因此,您可以像从任何其他异常一样从异常中获取堆栈跟踪。使用traceback.TracebackException
它(只需更换ex
您的除外):
print("".join(traceback.TracebackException.from_exception(ex).format())
Run Code Online (Sandbox Code Playgroud)
执行此操作的扩展示例和其他功能:
import traceback
try:
1/0
except Exception as ex:
print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__))) # This is True !!
print("".join(traceback.TracebackException.from_exception(ex).format()))
Run Code Online (Sandbox Code Playgroud)
输出将是这样的:
True
Traceback (most recent call last):
File "untidsfsdfsdftled.py", line 29, in <module>
1/0
ZeroDivisionError: division by zero
Run Code Online (Sandbox Code Playgroud)
对于那些使用Python-3的人
使用traceback
模块,exception.__traceback__
可以按如下方式提取堆栈跟踪:
traceback.extract_stack()
__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)
Run Code Online (Sandbox Code Playgroud)
一个简单的演示:
def foo():
try:
something_invalid()
except Exception as e:
print(exception_to_string(e))
def bar():
return foo()
Run Code Online (Sandbox Code Playgroud)
我们打电话时得到以下输出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
Run Code Online (Sandbox Code Playgroud)
小智 8
如果您想在未处理异常时获得相同的信息,您可以执行以下操作。做import traceback
然后:
try:
...
except Exception as e:
print(traceback.print_tb(e.__traceback__))
Run Code Online (Sandbox Code Playgroud)
我正在使用 Python 3.7。
您还可以考虑使用内置的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)
Run Code Online (Sandbox Code Playgroud)
我们得到这个异常输出......
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
Run Code Online (Sandbox Code Playgroud)
如果您的目标是使异常和堆栈跟踪消息看起来与 python 抛出错误时完全相同,则以下内容适用于 python 2+3:
import sys, traceback
def format_stacktrace():
parts = ["Traceback (most recent call last):\n"]
parts.extend(traceback.format_stack(limit=25)[:-2])
parts.extend(traceback.format_exception(*sys.exc_info())[1:])
return "".join(parts)
# EXAMPLE BELOW...
def a():
b()
def b():
c()
def c():
d()
def d():
assert False, "Noooh don't do it."
print("THIS IS THE FORMATTED STRING")
print("============================\n")
try:
a()
except:
stacktrace = format_stacktrace()
print(stacktrace)
print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()
Run Code Online (Sandbox Code Playgroud)
它的工作原理是format_stacktrace()
从堆栈中删除最后一个调用并加入其余调用。运行时,上面的示例给出了以下输出:
THIS IS THE FORMATTED STRING
============================
Traceback (most recent call last):
File "test.py", line 31, in <module>
a()
File "test.py", line 12, in a
b()
File "test.py", line 16, in b
c()
File "test.py", line 20, in c
d()
File "test.py", line 24, in d
assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.
THIS IS HOW PYTHON DOES IT
==========================
Traceback (most recent call last):
File "test.py", line 38, in <module>
a()
File "test.py", line 12, in a
b()
File "test.py", line 16, in b
c()
File "test.py", line 20, in c
d()
File "test.py", line 24, in d
assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.
Run Code Online (Sandbox Code Playgroud)