【问题标题】:Simple Python Logging Exception from Future来自 Future 的简单 Python 日志记录异常
【发布时间】:2017-10-12 06:03:48
【问题描述】:

这应该是一个非常简单的问题,但是在谷歌搜索、阅读文档和其他几个 SO 线程之后,我没有看到答案:如何使用 Python 标准日志记录异常?一个小问题是我从未来得到了例外。我自己不是在编写except 异常处理程序。理想情况下,我会得到异常消息、堆栈跟踪、发送的额外消息以及异常类型。这是一个显示我的问题的简单程序:

import logging
from concurrent.futures import ThreadPoolExecutor

logger = logging.getLogger(__name__)


def test_f(a, b=-99, c=50):
    logger.info("test_f a={} b={} c={}".format(a, b, c))


def future_callback_error_logger(future):
    e = future.exception()
    if e is not None:
        # This log statement does not seem to do what I want.
        # It logs "Executor Exception" with no information about the exception.
        # I would like to see the exception type, message, and stack trace.
        logger.error("Executor Exception", exc_info=e)


def submit_with_log_on_error(executor, func, *args, **kwargs):
    future = executor.submit(func, *args, **kwargs)
    future.add_done_callback(future_callback_error_logger)


if __name__ == "__main__":
    logging.basicConfig(level="DEBUG")

    logger.info("start")
    executor = ThreadPoolExecutor(max_workers=5)

    # This will work.
    submit_with_log_on_error(executor, test_f, 10, c=20)
    # This will intentionally trigger an error due to too many arguments.
    # I would like that error to be properly logged.
    submit_with_log_on_error(executor, test_f, 10, 20, 30, 40)
    # This will work.
    submit_with_log_on_error(executor, test_f, 50, c=60)

    executor.shutdown(True)
    logger.info("shutdown")

【问题讨论】:

    标签: python exception logging exception-handling


    【解决方案1】:

    要使用logger.exception 并获取回溯等,您需要位于一个 except 块内。不要检查future.exception(),它返回异常(如果有),而是使用future.result(),它引发异常(如果有)。

    所以,try 这个代替(不是双关语):

    def future_callback_error_logger(future):
        try:
            future.result()
        except Exception:
            logger.exception("Executor Exception")
    

    【讨论】:

    • add_done_callback docs.python.org/3/library/… 的文档中,它说“如果可调用对象引发异常子类,它将被记录并忽略。”我想知道谷歌搜索导致我来到这里的日志级别。如果异常已被记录并被忽略,您的解决方案是否必要?困惑
    • 那部分文档是在讨论由回调本身引起的任何异常(比如你写了一个有问题的回调)。它不是在谈论发送到线程池的工作代码引发的异常。所以,是的,仍然需要!
    • 请注意,如果由于某种原因您不想调用future.result() 而只是调用future.exception(),那么您也可以这样做:def future_callback_error_logger(future): try: e = future.exception() if e: raise e except Exception: logger.exception("Executor Exception") 来实现一样。
    • 好吧,抱歉,没有意识到 cmets 中没有保留换行符。我想说的是,您也可以在 try 中执行 raise e,并在此答案中的除块中执行 e = future.exception(),并获得类似的日志。
    猜你喜欢
    • 2011-10-23
    • 2020-12-31
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2016-04-22
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多