我想在不退出的情况下捕获和记录异常,例如,
try:
do_stuff()
except Exception as err:
print(Exception, err)
# I want to print the entire traceback here,
# not just the exception name and details
我想打印与抛出异常时打印的完全相同的输出,而不使用try/,只是拦截异常,并且我不希望它退出程序。
我想在不退出的情况下捕获和记录异常,例如,
try:
do_stuff()
except Exception as err:
print(Exception, err)
# I want to print the entire traceback here,
# not just the exception name and details
我想打印与抛出异常时打印的完全相同的输出,而不使用try/,只是拦截异常,并且我不希望它退出程序。
当前回答
您需要将try/except放在可能发生错误的最内层循环中,即。
for i in something:
for j in somethingelse:
for k in whatever:
try:
something_complex(i, j, k)
except Exception, e:
print e
try:
something_less_complex(i, j)
except Exception, e:
print e
... 等等
换句话说,您需要将可能在try/中失败的语句包装在尽可能具体的内部循环中。
其他回答
除了Aaron Hall的回答之外,如果您正在记录日志,但不想使用logging.exception()(因为它在ERROR级别记录日志),您可以使用更低的级别并传递exc_info=True。如。
try:
do_something_that_might_error()
except Exception:
logging.info('General exception noted.', exc_info=True)
关于这个答案的注释:print(traceback.format_exc())对我来说比traceback.print_exc()更好。对于后者,hello有时会奇怪地与回溯文本“混合”在一起,比如两者都想同时写入stdout或stderr,产生奇怪的输出(至少在从文本编辑器内部构建并在“构建结果”面板中查看输出时)。
回溯(最近一次调用): 文件“C:\Users\User\Desktop\test.py”,第7行,在 地狱do_stuff () 文件“C:\Users\User\Desktop\test.py”,第4行,do_stuff 1/0 ZeroDivisionError:整数除法或对0取模 o [0.1s完成]
所以我用:
import traceback, sys
def do_stuff():
1/0
try:
do_stuff()
except Exception:
print(traceback.format_exc())
print('hello')
traceback.format_exception (exception_object)
如果你只有异常对象,你可以从Python 3中的任何代码点获得字符串形式的回溯:
import traceback
''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
完整的例子:
#!/usr/bin/env python3
import traceback
def f():
g()
def g():
raise Exception('asdf')
try:
g()
except Exception as e:
exc_obj = e
tb_str = ''.join(traceback.format_exception(None, exc_obj, exc_obj.__traceback__))
print(tb_str)
输出:
Traceback (most recent call last):
File "./main.py", line 12, in <module>
g()
File "./main.py", line 9, in g
raise Exception('asdf')
Exception: asdf
文档:https://docs.python.org/3.9/library/traceback.html traceback.format_exception
请参见:从异常对象中提取回溯信息
在Python 3.9中测试
如何在不停止程序的情况下打印完整的回溯?
当你不想因为一个错误而停止你的程序时,你需要用try/except来处理这个错误:
try:
do_something_that_might_error()
except Exception as error:
handle_the_error(error)
要提取完整的回溯,我们将使用标准库中的traceback模块:
import traceback
并创建一个相当复杂的stacktrace来演示我们得到完整的stacktrace:
def raise_error():
raise RuntimeError('something bad happened!')
def do_something_that_might_error():
raise_error()
印刷
要打印完整的回溯,请使用traceback。print_exc方法:
try:
do_something_that_might_error()
except Exception as error:
traceback.print_exc()
打印:
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 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!
或者,您可能只想要字符串,在这种情况下,您将需要回溯。Format_exc函数改为:
try:
do_something_that_might_error()
except Exception as error:
logger.debug(traceback.format_exc())
日志:
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!
结论
对于这三个选项,我们看到我们得到的输出和我们有错误时是一样的:
>>> 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!
使用哪种
性能问题在这里并不重要,因为IO通常占主导地位。我更喜欢,因为它精确地以向前兼容的方式执行请求:
logger.exception(error)
日志级别和输出可以调整,这样就可以很容易地关闭,而不需要修改代码。通常做直接需要的是最有效的方法。
如果你已经有了一个Error对象,并且你想打印整个东西,你需要做这个有点尴尬的调用:
import traceback
traceback.print_exception(type(err), err, err.__traceback__)
没错,print_exception接受三个位置参数:异常的类型、实际的异常对象和异常自身的内部回溯属性。
在python 3.5或更高版本中,类型(err)是可选的…但它是一个位置参数,所以你仍然需要显式地在它的位置传递None。
traceback.print_exception(None, err, err.__traceback__)
我不知道为什么所有这些不只是traceback.print_exception(err)。为什么你会想打印出一个错误,以及一个回溯,而不是属于该错误的,这超出了我的理解。