另一种方法是将记录器包装在一个对象中,该对象将调用转换write
为记录器的log
方法。
Ferry Boender 就是这样做的,根据 GPL 许可在其网站上的帖子中提供。下面的代码基于此,但解决了原始代码的两个问题:
- 该类没有实现程序退出时调用的 flush 方法。
- 该类不会缓冲换行符上的写入,因为 io.TextIOWrapper 对象应该会在奇数点产生换行符。
import logging
import sys
class StreamToLogger(object):
"""
Fake file-like stream object that redirects writes to a logger instance.
"""
def __init__(self, logger, log_level=logging.INFO):
self.logger = logger
self.log_level = log_level
self.linebuf = ''
def write(self, buf):
temp_linebuf = self.linebuf + buf
self.linebuf = ''
for line in temp_linebuf.splitlines(True):
# From the io.TextIOWrapper docs:
# On output, if newline is None, any '\n' characters written
# are translated to the system default line separator.
# By default sys.stdout.write() expects '\n' newlines and then
# translates them so this is still cross platform.
if line[-1] == '\n':
self.logger.log(self.log_level, line.rstrip())
else:
self.linebuf += line
def flush(self):
if self.linebuf != '':
self.logger.log(self.log_level, self.linebuf.rstrip())
self.linebuf = ''
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s:%(levelname)s:%(name)s:%(message)s',
filename="out.log",
filemode='a'
)
stdout_logger = logging.getLogger('STDOUT')
sl = StreamToLogger(stdout_logger, logging.INFO)
sys.stdout = sl
stderr_logger = logging.getLogger('STDERR')
sl = StreamToLogger(stderr_logger, logging.ERROR)
sys.stderr = sl
这使您可以轻松地将所有输出路由到您选择的记录器。如果需要,如果您以后需要恢复它,您可以在替换它之前保存sys.stdout
和/或按照其他人在此线程中提到的方法。sys.stderr