【问题标题】:python logging.critical() to raise exception and dump stacktrace and diepython logging.critical() 引发异常并转储堆栈跟踪并死掉
【发布时间】:2018-06-19 10:21:05
【问题描述】:

我正在从 perl (log4perl) 和 java (slf4j) 移植一些代码。一切都很好,除了 logging.critical() 不会像在其他框架中那样转储堆栈跟踪并死掉,需要添加很多额外的代码,logger.exception() 也只会写入错误。

今天我这样做:

try:
    errmsg = "--id={} not found on --host={}".format(args.siteid, args.host)
    raise GX8Exception(errmsg)
except GX8Exception as e:
    log.exception(e)
    sys.exit(-1)

这会产生:

2018-01-10 10:09:56,814 [ERROR   ] root         --id=7A4A7845-7559-4F89-B678-8ADFECF5F7C3 not found on --host=welfare-qa
Traceback (most recent call last):
  File "./gx8-controller.py", line 85, in <module>
    raise GX8Exception(errmsg)
GX8Exception: --id=7A4A7845-7559-4F89-B678-8ADFECF5F7C3 not found on --host=welfare-qa

有没有办法配置 pythonmodule logger 来做到这一点,或者任何其他框架来做同样的事情:

log.critical("--id={} not found on --host={}".format(args.siteid, args.host))

【问题讨论】:

    标签: python-3.x logging exception-handling


    【解决方案1】:

    一种方法是创建一个自定义处理程序,它除了将日志消息传递给它的超级,然后在日志级别足够高时退出:

    import logging
    
    class ExitOnExceptionHandler(logging.StreamHandler):
        def emit(self, record):
            super().emit(record)
            if record.levelno in (logging.ERROR, logging.CRITICAL):
                raise SystemExit(-1)
    
    
    logging.basicConfig(handlers=[ExitOnExceptionHandler()], level=logging.DEBUG)
    
    logger = logging.getLogger('MYTHING')
    
    def causeAProblem():
        try:
            raise ValueError("Oh no!")
        except Exception as e:
            logger.exception(e)
    
    logger.warning('Going to try something risky...')
    causeAProblem()
    print("This won't get printed")
    

    输出:

    rat@pandion:~$ python test.py
    ERROR:root:Oh no!
    Traceback (most recent call last):
      File "test.py", line 14, in causeAProblem
        raise ValueError("Oh no!")
    ValueError: Oh no!
    rat@pandion:~$ echo $?
    255
    

    但是,这可能会导致代码用户出现意外行为。如果您想记录异常并退出,那么简单地不捕获异常会更直接。如果您想记录回溯并退出代码当前调用 logging.critical 的任何位置,请将其更改为引发异常。

    【讨论】:

    • 感谢 ExitOnExceptionHandler 类,这是我的缺失点。 int perl 和 java 代码 log.fatal() 用于杀死代码,因此它应该在这里正常工作。
    【解决方案2】:

    我继承了一些无法更改处理程序类的代码。我求助于处理程序的运行时修补,这是@nathan-vērzemnieks 解决方案的一个变体:

    
    import types
    
    def patch_logging_handler(logger):
        def custom_emit(self, record):
            self.orig_emit(record)
            if record.levelno == logging.FATAL:
                raise SystemExit(-1)
    
        handler = logger.handlers[0]
        setattr(handler, 'orig_emit', handler.emit)
        setattr(handler, 'emit', types.MethodType(custom_emit, handler))
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 2017-08-06
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多