Simple Python log exclusion from the future

This should be a very simple question, but after googling, reading docs, and a few other SO threads, I don't see an answer: How do I log the exception using Python's standard logging? One small wrinkle is that I get a Future Exception. I don't write an exception handler myself except

. Ideally, I would get an exception message, a stack trace, an additional message added, and possibly the type of the exception. Here's a simple program that shows my problem:

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")

      

+3


source to share


1 answer


In order to use logger.exception

and get tracing, etc., you must be inside an except block. Instead of checking future.exception()

that returns an exception (if any), use future.result()

one that throws an exception (if any).

So, try

instead (no pun intended):



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

      

+2


source







All Articles