2017-09-27 67 views
0

logger.exception如果在池中执行,则不显示堆栈跟踪,并且将错误消息传递为arg。Python - 如何在新线程中获取堆栈跟踪

设置:

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

不显示堆栈跟踪:

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

显示堆栈跟踪:

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

新的线程意味着新的堆栈。 –

+0

但是,如果像'logger.exception(e)' – garg10may

+0

这样提交,它会起作用,因为你在调用'submit'前做了日志记录。它实际上会被记录调用的结果调用,AFAIR应该是'None'。 –

回答

2

此代码的工作,因为被提交到线程池之前被记录的问题:

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,*指定参数时,** 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将被转换为字符串并用作记录回溯的消息。

+0

然后我应该用'logger.error,e,exc_info = sys.exc_info()'调用,因为'logger.exception'只是'logger.error' with'exc_info = True' – garg10may

+0

你很安全的调用logger.exception这里只要你通过'exc_info'参数提供异常信息,但是,我确实认为'logger.error'是更好的选择。 – jszakmeister