Python - 如何在新线程中获取堆栈跟踪

时间:2017-09-27 06:41:01

标签: python logging threadpool

如果在池中执行,

logger.exception不显示堆栈跟踪,并且错误消息以arg形式传递。

设定:

import logging
from concurrent.futures import ThreadPoolExecutor
logger = logging.getLogger('custom')
ch = logging.StreamHandler()
logger.addHandler(ch)
logger.setLevel(logging.INFO)
executor = ThreadPoolExecutor(3)

不显示stacktrace:

try:
    1/0
except Exception as e:
    executor.submit(logger.exception, e)

显示stackTrace:

try:
    1/0
except Exception as e:
    executor.submit(logger.exception(e))

1 个答案:

答案 0 :(得分:3)

此代码有效,因为在提交给线程池之前记录了该问题:

try:
    1/0
except Exception as e:
    executor.submit(logger.exception(e))

实际上,您发送给线程池的是None

这不起作用,因为在logger.exception调用中发生了一些神奇的事情,当它在异常处理上下文之外时它不起作用(当它在另一个线程中运行时它将会是这样):

try:
    1/0
except Exception as e:
    executor.submit(logger.exception, e)

检查文档通常很有帮助。对于.exception() method文档说:

  

在此记录器上记录级别为ERROR的消息。参数被解释为debug()。异常信息将添加到日志消息中。只应从异常处理程序调用此方法。

.debug()文档的相关部分是:

  

logging.debug(msg,* args,** kwargs)

     

在根记录器上记录级别为DEBUG的消息。 msg是消息格式字符串,args是使用字符串格式化运算符合并到msg中的参数。 (请注意,这意味着您可以使用格式字符串中的关键字以及单个字典参数。)

     

kwargs中有三个关键字参数被检查:exc_info,如果它不计算为false,则会将异常信息添加到日志消息中。如果提供了异常元组(以sys.exc_info()返回的格式),则使用它;否则,调用sys.exc_info()以获取异常信息。

所以,这一行:

executor.submit(logger.exception, e)

将调用在处理日志记录的线程中调用原因sys.exc_info(),该线程没有异常信息 - 因此不会记录回溯。相反,你想要:

executor.submit(logger.exception, "error occurred", exc_info=sys.exc_info())

所以在它的最终形式中,它看起来像:

try:
    1/0
except Exception as e:
    executor.submit(logger.exception, "error occurred", exc_info=sys.exc_info())

更好的做法是避免logger.exception()来电,而只需使用logger.error()

try:
    1/0
except Exception as e:
    executor.submit(logger.error, "error occurred", exc_info=sys.exc_info())

如果您希望将异常消息作为日志消息,则可以执行此操作(类似于您在原始代码中所做的操作):

try:
    1/0
except Exception as e:
    executor.submit(logger.error, e, exc_info=sys.exc_info())

e将转换为字符串并用作记录回溯的消息。