简体   繁体   中英

How to capture the output on stderr of a logger using a StreamHandler?

Redirecting the output of normal logging works fine:

import contextlib
import io
import logging

std_out_capture = io.StringIO()
with contextlib.redirect_stderr(std_out_capture):
    logging.error('Hi.')

output = std_out_capture.getvalue()
print(f'output: {output}')

output:

output: ERROR:root:Hi.

However when changing the log format using logging.basicConfig

import contextlib
import io
import logging

log_format = '[%(threadName)s] [%(levelname)s] %(message)s'
logging.basicConfig(format=log_format)

std_out_capture = io.StringIO()
with contextlib.redirect_stderr(std_out_capture):
    logging.error('Hi.')

output = std_out_capture.getvalue()
print(f'output: {output}')

the output is:

output: 
[MainThread] [ERROR] Hi.

So the output is not captured any more.

My guess is this is because

logging.basicConfig(**kwargs): Does basic configuration for the logging system by creating a StreamHandler with a default Formatter and adding it to the root logger.

( https://docs.python.org/3/library/logging.html#logging.basicConfig )

and StreamHandler is working in a separate thread, so it's output is not captured.

For unit testing I would like to capture it anyways. How can I do this?

You'll have to pull the logging configuration into the with statement-body so StreamHandler already gets initialized with the altered stderr :

import contextlib
import io
import logging

std_out_capture = io.StringIO()
with contextlib.redirect_stderr(std_out_capture):
    log_format = '[%(threadName)s] [%(levelname)s] %(message)s'
    logging.basicConfig(format=log_format)
    logging.error('Hi.')

output = std_out_capture.getvalue()
print(f'output: {output}')
# output: [MainThread] [ERROR] Hi.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM