python logging.critical() 引发异常并转储堆栈跟踪并死掉
python logging.critical() to raise exception and dump stacktrace and die
我正在从 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))
一种方法是创建一个自定义处理程序,该处理程序除了将日志消息传递给它的 super 外什么都不做,然后在日志级别足够高时退出:
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
,请改为引发异常。
我继承了一些无法更改处理程序的代码 class。我求助于 运行 处理程序的时间修补,这是@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))
Nathans 的回答很棒!找了好久
只会补充说你也可以这样做:
if record.levelno >= logging.ERROR:
而不是
if record.levelno in (logging.ERROR, logging.CRITICAL):
设置导致退出的最低级别。
我正在从 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))
一种方法是创建一个自定义处理程序,该处理程序除了将日志消息传递给它的 super 外什么都不做,然后在日志级别足够高时退出:
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
,请改为引发异常。
我继承了一些无法更改处理程序的代码 class。我求助于 运行 处理程序的时间修补,这是@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))
Nathans 的回答很棒!找了好久
只会补充说你也可以这样做:
if record.levelno >= logging.ERROR:
而不是
if record.levelno in (logging.ERROR, logging.CRITICAL):
设置导致退出的最低级别。