如果 python 日志记录处理程序引发异常会怎样?

What happens if a python logging handler raises an exception?

如果日志处理程序失败会怎样?

假设我们的日志配置是用一些日志处理程序定义的。有一种方法可以自定义这样的处理程序,因此我可以在任何处理程序的 emit 函数上定义任何操作。 此外,假设其中一个处理程序引发异常。问题是,无论如何,剩下的那些的emit函数还是会被触发,或者有的会悄无声息的失败。

一个可能的用例是使用预定义的 SMTPHandler,但要关闭互联网。如果在作用域中定义了 RotatingFileHandler,在这种情况下它会失败吗,或者处理程序的发出是独立发生的?

我看到该示例的三种可能情况:

  1. RotatingFileHandler 始终触发,因为处理程序是独立处理的
  2. RotatingFileHandler 的失败是随机发生的,按照处理程序的顺序
  3. 如果其中任何一个失败,则没有处理程序成功

Python 标准库处理程序的构建考虑到了稳健性。如果在要求处理程序发出记录时引发异常,所有标准库实现都会捕获异常并调用 Handler.handleError().

默认情况下,如果 sys.stderr 未设置为 None,则调用 Handler.handleError() 会重新引发异常 。在生产系统中,您要设置 logging.raiseExceptions = False,此时异常会被静默忽略,并且继续记录日志,就好像什么都没发生一样。

来自文档:

This method should be called from handlers when an exception is encountered during an emit() call. If the module-level attribute raiseExceptions is False, exceptions get silently ignored. This is what is mostly wanted for a logging system - most users will not care about errors in the logging system, they are more interested in application errors. You could, however, replace this with a custom handler if you wish. The specified record is the one which was being processed when the exception occurred. (The default value of raiseExceptions is True, as that is more useful during development).

所以如果logging.raiseExceptions留给默认的True,那么就看哪个handler先被调用的handler注册顺序了。在引发异常之前调用的任何处理程序都将成功。

如果 logging.raiseExceptions 已设置为 False,将调用所有处理程序,即使其中一个处理程序因异常而失败。