logging.raiseExceptions = True不会重新引发异常。

4
我正在尝试在我的代码中实现以下功能:
  • 记录信息、错误消息和异常到控制台和/或文件,而不中断程序流程(即,吞噬异常,某种“运行模式”)
  • 通过设置develop=True标志进入开发模式,在此模式下将引发异常
目前,我正在使用Python3的logging模块,该模块(根据此文档)应内置了这个功能。然后标志是logging.raiseExceptions = True
但是,在MWE中,我无法让它工作:无论我如何设置标志,我抛出的异常都没有被重新引发。
# mwe.py
import logging
import logging.config

if __name__ == '__main__':
    # Configure logging and set flag to raise exceptions
    logging.config.fileConfig('log.conf')
    logging.raiseExceptions = True

    logger = logging.getLogger('root')

    logger.info('Started')

    # Test whether exceptions get raised
    try:
        raise RuntimeError("Ooops.")
    except RuntimeError:
        try:
            logger.exception('There was an oops.')
            # which is the same as logger.error('...', exc_info=True)
        except:
            print("GOTCHA! Exception was re-raised.")

    logger.info('Finished')

相应的配置文件

# log.conf
[loggers]
keys=root

[handlers]
keys=consoleHandler

[formatters]
keys=consoleFormatter

[logger_root]
handlers=consoleHandler
level=DEBUG

[handler_consoleHandler]
class=logging.StreamHandler
formatter=consoleFormatter
args=(sys.stdout,)

[formatter_consoleFormatter]
format=%(filename)s (%(lineno)d) %(levelname)-8s - %(message)s

这会产生以下输出结果:
mwe.py (12) INFO     - Started
mwe.py (19) ERROR    - There was an oops.
Traceback (most recent call last):
  File "mwe.py", line 16, in <module>
    raise RuntimeError("Ooops.")
RuntimeError: Ooops.
mwe.py (24) INFO     - Finished

为什么我没有进入“GOTCHA”部分,尽管raiseExceptions的默认值为True,而且我还将其设置为True?我的配置有什么问题吗?
或者我对使用logging有一些误解吗?

(小奖励问题:是否有一种方法在log.conf文件中配置raiseException标志?)

1个回答

9
你误解了。这不会重新引发任何自定义异常。它的目的是更改日志模块的默认行为,即吞噬内部日志异常,例如配置错误的记录器尝试写入没有权限写入的文件。默认情况下,这将默默失败,并设置logging.raiseException = True将导致记录器配置错误或日志模块中的任何其他问题引发异常,您必须处理此异常。
现在来谈谈你想要实现的目标。记录异常回溯而不抑制异常(让其传播)是默认行为。如果未配置记录,则回溯跟踪到stderr。如果已配置记录,则由记录处理程序写入所需位置。 因此,为了实现您的目标,您根本不应处理异常。但是,如果您知道如何处理异常(即您知道引起异常的原因),则通常无需记录回溯跟踪。 如果您坚持仍然可以在except RuntimeError子句中使用logger.exception(...)并使用纯raise重新引发异常:
try:
    raise RuntimeError("Ooops.")
except RuntimeError:
    logger.exception('There was an oops.')
    raise

啊,我明白了。感谢您的澄清!在这里,自定义异常的最佳实践是什么?如果我希望程序在引发异常时不停止(例如由于某些错误的输入数据),该怎么办?我应该首先不引发任何自定义异常,只记录错误;还是应该引发自定义异常,然后自动处理它们(例如通过 sys.excepthook)...我有点困惑。 :/ - blsqr
只需在try...except块中使用,无需在except块中重新引发它。自定义异常也可以。 - ElmoVanKielmo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接