如何使用StreamHandler在记录器的stderr上捕获输出?

时间:2018-08-14 12:23:52

标签: python python-3.x logging stdout stderr

重定向普通日志记录的输出效果很好:

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: ERROR:root:Hi.

但是,使用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}')

输出为:

output: 
[MainThread] [ERROR] Hi.

因此不再捕获输出。

我的猜测是因为

  

logging.basicConfig(** kwargs):通过创建带有默认Formatter的StreamHandler并将其添加到根记录器中,对记录系统进行基本配置。

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

StreamHandler在单独的线程中工作,因此未捕获其输出。

对于单元测试,我还是想捕获它。我该怎么办?

1 个答案:

答案 0 :(得分:1)

您必须将日志记录配置放入with语句主体中,以便StreamHandler已使用更改后的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.