向sys.excepthook添加功能
问题内容:
假设我有类似的东西,它将未处理的异常发送到logging.critical()
:
import sys
def register_handler():
orig_excepthook = sys.excepthook
def error_catcher(*exc_info):
import logging
log = logging.getLogger(__name__)
log.critical("Unhandled exception", exc_info=exc_info)
orig_excepthook(*exc_info)
sys.excepthook = error_catcher
有用:
import logging
logging.basicConfig()
register_handler()
undefined() # logs, then runs original excepthook
但是,如果register_handler()
多次error_catcher
调用,则会在一个链中调用多个,并且记录消息会出现多次。
我可以想到几种方法,但是它们都不是一种特别好的方法(例如检查sys.excepthook
error_catcher函数是否有效,或者在模块上使用“
have_registered”属性以避免重复注册)
有推荐的方法吗?
问题答案:
具有模块级别的“已注册钩子”变量似乎是最简单,最可靠的方法。
其他可能的解决方案在某些(而不是晦涩的)情况下sys.excepthook
会失效-
如果应用程序注册了一个自定义项excepthook
,则检查内置函数是否会失败,excepthook
在函数定义时存储原始函数将破坏随后注册的钩子函数。
import sys
_hook_registered = False
def register_handler(force = False):
global _hook_registered
if _hook_registered and not force:
return
orig_excepthook = sys.excepthook
def error_catcher(*exc_info):
import logging
log = logging.getLogger(__name__)
log.critical("Unhandled exception", exc_info=exc_info)
orig_excepthook(*exc_info)
sys.excepthook = error_catcher
_hook_registered = True