如何通过日志模块而不是stderr导致未捕获的异常输出?
我意识到最好的办法是:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
但我的情况是,如果在没有捕获异常时自动调用logging.exception(…),那就太好了。
如何通过日志模块而不是stderr导致未捕获的异常输出?
我意识到最好的办法是:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
但我的情况是,如果在没有捕获异常时自动调用logging.exception(…),那就太好了。
当前回答
以Jacinda的回答为基础,但使用记录器对象:
def catchException(logger, typ, value, traceback):
logger.critical("My Error Information")
logger.critical("Type: %s" % typ)
logger.critical("Value: %s" % value)
logger.critical("Traceback: %s" % traceback)
# Use a partially applied function
func = lambda typ, value, traceback: catchException(logger, typ, value, traceback)
sys.excepthook = func
其他回答
也许你可以在模块的顶部做一些事情,将stderr重定向到一个文件,然后在底部记录该文件
sock = open('error.log', 'w')
sys.stderr = sock
doSomething() #makes errors and they will log to error.log
logging.exception(open('error.log', 'r').read() )
为什么不:
import sys
import logging
import traceback
def log_except_hook(*exc_info):
text = "".join(traceback.format_exception(*exc_info()))
logging.error("Unhandled exception: %s", text)
sys.excepthook = log_except_hook
None()
下面是使用sys的输出。如上图所示:
$ python tb.py
ERROR:root:Unhandled exception: Traceback (most recent call last):
File "tb.py", line 11, in <module>
None()
TypeError: 'NoneType' object is not callable
下面是使用sys. js的输出。但是thook评论道:
$ python tb.py
Traceback (most recent call last):
File "tb.py", line 11, in <module>
None()
TypeError: 'NoneType' object is not callable
唯一的区别是前者在第一行的开头有ERROR:root:Unhandled异常。
包装你的应用程序入口调用在一个尝试…Except块,这样您就能够捕获和记录(可能还会重新引发)所有未捕获的异常。例如:
if __name__ == '__main__':
main()
这样做:
if __name__ == '__main__':
try:
main()
except Exception as e:
logger.exception(e)
raise
虽然@gnu_lorien的回答给了我一个很好的起点,但我的程序在第一个异常时崩溃了。
我提供了一个定制的(和/或)改进的解决方案,它可以无声地记录带有@handle_error装饰的函数的异常。
import logging
__author__ = 'ahmed'
logging.basicConfig(filename='error.log', level=logging.DEBUG)
def handle_exception(exc_type, exc_value, exc_traceback):
import sys
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
logging.critical(exc_value.message, exc_info=(exc_type, exc_value, exc_traceback))
def handle_error(func):
import sys
def __inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception, e:
exc_type, exc_value, exc_tb = sys.exc_info()
handle_exception(exc_type, exc_value, exc_tb)
finally:
print(e.message)
return __inner
@handle_error
def main():
raise RuntimeError("RuntimeError")
if __name__ == "__main__":
for _ in xrange(1, 20):
main()
为了回答在已接受答案的评论部分讨论的zeus先生的问题,我使用它来记录交互式控制台中未捕获的异常(使用PyCharm 2018-2019测试)。我发现了。excepthook不能在python shell中工作,所以我深入研究了一下,发现我可以使用sys。exc_info代替。然而,系统。与sys不同,Exc_info不带参数。除了thook,它有3个参数。
在这里,我使用了两个sys。除了thook和sys。Exc_info来记录交互式控制台和带有包装器函数的脚本中的两个异常。要将钩子函数附加到两个函数,我有两个不同的接口,这取决于是否给出参数。
代码如下:
def log_exception(exctype, value, traceback):
logger.error("Uncaught exception occurred!",
exc_info=(exctype, value, traceback))
def attach_hook(hook_func, run_func):
def inner(*args, **kwargs):
if not (args or kwargs):
# This condition is for sys.exc_info
local_args = run_func()
hook_func(*local_args)
else:
# This condition is for sys.excepthook
hook_func(*args, **kwargs)
return run_func(*args, **kwargs)
return inner
sys.exc_info = attach_hook(log_exception, sys.exc_info)
sys.excepthook = attach_hook(log_exception, sys.excepthook)
日志记录设置可以在gnu_lorien的回答中找到。