我正在编写一个程序来解析10个网站,查找数据文件,保存文件,然后解析它们以生成可以在NumPy库中使用的数据 . 这个文件通过坏链接,格式不良的XML,缺少条目以及其他我尚未归类的东西会遇到 tons 错误 . 我最初制作这个程序来处理这样的错误:
try:
do_stuff()
except:
pass
但现在我想记录错误:
try:
do_stuff()
except Exception, err:
print Exception, err
请注意,这是打印到日志文件以供以后查看 . 这通常会打印非常无用的数据 . 我想要的是打印错误触发时打印的完全相同的行,没有try-except拦截异常,但我不希望它暂停我的程序,因为它嵌套在一系列for循环中,我想看完成了 .
10 回答
你想要traceback模块 . 它可以让你像Python一样打印堆栈转储 . 特别是,print_last函数将打印最后一个异常和堆栈跟踪 .
其他一些答案已经指出traceback模块 .
请注意,对于
print_exc
,在某些极端情况下,您将无法获得您期望的结果 . 在Python 2.x中:...将显示最后一个异常的回溯:
If you really need to access the original traceback 一个解决方案是缓存从局部变量exc_info返回的异常信息,并使用print_exception显示:
生产环境 :
尽管如此,很少有陷阱:
另一方面,通过允许您访问与异常关联的回溯,Python 3产生了一个不太令人惊讶的结果:
...将显示:
traceback.format_exc()或sys.exc_info()会产生更多信息,如果这是你想要的 .
如果您正在调试并且只想查看当前堆栈跟踪,则只需调用:
traceback.print_stack()
没有必要手动引发异常只是为了再次捕获它 .
如果您不想在出错时暂停程序,则需要使用try / except来处理该错误:
要提取完整的回溯,我们将使用标准库中的
traceback
模块:并创建一个相当复杂的堆栈跟踪来演示我们获得完整的堆栈跟踪:
印刷
要打印完整的回溯,请使用
traceback.print_exc
方法:哪个印刷品:
优于打印,记录:
但是,最佳做法是为模块设置 Logger . 它将知道模块的名称并能够更改级别(以及其他属性,例如处理程序)
在这种情况下,您将需要
logger.exception
函数:哪些日志:
或者你可能只想要字符串,在这种情况下,你需要
traceback.format_exc
函数代替:哪些日志:
结论
对于所有三个选项,我们看到输出与出错时相同:
要获得精确的堆栈跟踪,作为一个字符串,如果没有try / except可以提升它,只需将它放在捕获有问题的异常的except块中 .
以下是如何使用它(假设
flaky_func
已定义,log
调用您最喜欢的日志记录系统):grab 并重新提升
KeyboardInterrupt
是一个好主意,这样你仍然可以使用Ctrl-C杀死程序 . 记录超出了问题的范围,但一个很好的选择是logging . sys和traceback模块的文档 .除了@Aaron Hall 's answer, if you are logging, but don' t想要使用
logging.exception()
(因为它记录在ERROR级别),你可以使用较低级别并传递exc_info=True
. 例如您需要将try / except放在最可能发生错误的内环中,即
... 等等
换句话说,您将需要在try / except中包含可能失败的语句可能,尽可能在最内圈 .
关于this answer评论的评论:
print(traceback.format_exc())
对我来说比traceback.print_exc()
更好 . 对于后者,hello
有时奇怪"mixed"带有回溯文本,就像两个人都想同时写入stdout或stderr一样,产生奇怪的输出(至少在从文本编辑器内部构建并查看"Build results"中的输出时)面板) .所以我使用:
首先,不要使用
print
进行日志记录,有稳定,经过验证且经过深思熟虑的stdlib模块:logging . 你绝对应该使用它 .其次,当有本地和简单的方法时,不要试图搞乱无关的工具 . 就这个:
而已 . 你现在完成了 .
任何对事情如何深入感兴趣的人的解释
log.exception
做的实际上只是调用log.error
(也就是具有级别ERROR
的日志事件)然后打印回溯 .为什么它更好?
嗯,这里有一些注意事项:
这是对的;
很简单;
很简单 .
为什么没有人不应该使用treceback,也不应该用exc_info = True调用logger,也不能用sys.exc_info弄脏他/她的手?
好吧,因为!它们都存在于不同的目的 . 例如,
traceback.print_exc
的输出与解释器本身产生的回溯略有不同 . 如果你打算使用它,你会混淆任何会用你的日志敲打他的人 .传递
exc_info=True
来记录电话是不合适的 . 但是,当您捕获可恢复的错误并且想要使用回溯记录它们时(例如,使用,例如INFO
级别),它非常有用,因为log.exception
只生成一个级别的日志 -ERROR
.而你绝对应该尽可能地避免弄乱
sys.exc_info
. 它不是公共接口,它是内部接口 - 如果你肯定知道你在做什么,你可以使用它 . 它不仅用于打印异常 .