Jac*_*ble 157 python logging exception-handling
如何通过logging模块而不是通过模块输出未捕获的异常stderr?
我意识到这样做的最好方法是:
try:
raise Exception, 'Throwing a boring exception'
except Exception, e:
logging.exception(e)
Run Code Online (Sandbox Code Playgroud)
但是我的情况是如果在没有捕获到异常的情况下自动调用它会非常好logging.exception(...).
gnu*_*ien 155
这是一个完整的小例子,其中还包括一些其他技巧:
import sys
import logging
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(stream=sys.stdout)
logger.addHandler(handler)
def handle_exception(exc_type, exc_value, exc_traceback):
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
if __name__ == "__main__":
raise RuntimeError("Test unhandled")
Run Code Online (Sandbox Code Playgroud)
忽略KeyboardInterrupt,这样一个控制台python程序可以用Ctrl + C退出.
完全依靠python的日志记录模块来格式化异常.
使用带有示例处理程序的自定义记录器.这个更改未处理的异常以转到stdout而不是stderr,但是您可以将相同样式的各种处理程序添加到logger对象.
Jac*_*nda 132
正如Ned指出的那样,sys.excepthook每次引发异常并且未被捕获时都会调用它.这样做的实际意义是,在您的代码中,您可以覆盖默认行为,sys.excepthook以执行您想要的任何操作(包括使用logging.exception).
作为一个稻草人的例子:
>>> import sys
>>> def foo(exctype, value, tb):
... print 'My Error Information'
... print 'Type:', exctype
... print 'Value:', value
... print 'Traceback:', tb
...
Run Code Online (Sandbox Code Playgroud)
覆盖sys.excepthook:
>>> sys.excepthook = foo
Run Code Online (Sandbox Code Playgroud)
提交明显的语法错误(省略冒号)并获取自定义错误信息:
>>> def bar(a, b)
My Error Information
Type: <type 'exceptions.SyntaxError'>
Value: invalid syntax (<stdin>, line 1)
Traceback: None
Run Code Online (Sandbox Code Playgroud)
有关以下内容的更多信息sys.excepthook:http://docs.python.org/library/sys.html#sys.excepthook
Ned*_*der 26
sys.excepthook如果未捕获异常,则将调用该方法:http://docs.python.org/library/sys.html#sys.excepthook
当引发异常并且未被捕获时,解释器使用三个参数调用sys.excepthook,异常类,异常实例和回溯对象.在交互式会话中,这发生在控制返回到提示之前; 在Python程序中,这发生在程序退出之前.可以通过为sys.excepthook分配另一个三参数函数来自定义这种顶级异常的处理.
Tia*_*nho 20
为什么不:
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()
Run Code Online (Sandbox Code Playgroud)
sys.excepthook如上所示,输出如下:
$ 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
Run Code Online (Sandbox Code Playgroud)
以下是sys.excepthook注释掉的输出:
$ python tb.py
Traceback (most recent call last):
File "tb.py", line 11, in <module>
None()
TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)
唯一的区别是前者ERROR:root:Unhandled exception:在第一行的开头.
就我而言(使用python 3),当使用 @Jacinda 的答案时,回溯的内容未打印。相反,它只是打印对象本身:<traceback object at 0x7f90299b7b90>。
相反,我这样做:
import sys
import logging
import traceback
def custom_excepthook(exc_type, exc_value, exc_traceback):
# Do not print exception when user cancels the program
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
logging.error("An uncaught exception occurred:")
logging.error("Type: %s", exc_type)
logging.error("Value: %s", exc_value)
if exc_traceback:
format_exception = traceback.format_tb(exc_traceback)
for line in format_exception:
logging.error(repr(line))
sys.excepthook = custom_excepthook
Run Code Online (Sandbox Code Playgroud)
以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
Run Code Online (Sandbox Code Playgroud)
尽管@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()
Run Code Online (Sandbox Code Playgroud)
将您的应用程序入口调用包装在一个try...except块中,以便您能够捕获并记录(并且可能重新引发)所有未捕获的异常。例如,而不是:
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
做这个:
if __name__ == '__main__':
try:
main()
except Exception as e:
logger.exception(e)
raise
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
43298 次 |
| 最近记录: |