python3 / logging:可选择写入多个流

时间:2017-11-06 18:44:52

标签: python-3.x logging

我成功使用python3程序中的logging模块将日志消息发送到日志文件,例如/var/log/myprogram.log。在某些情况下,我希望这些消息的子集也转到stdout,它们通过我的logging.Logger实例格式化,就像它们转到日志文件时格式化一样。

假设我的记录器实例被称为loginstance,我想在loginstance.log(level, msg)周围添加某种包装,让我选择消息是否仅转到/var/log/myprogram.log,或者它是否去了stdout,如下:

# Assume `loginstance` has already been instantiated
# as a global, and that it knows to send logging info
# to `/var/log/myprogram.log` by default.
def mylogger(level, msg, with_stdout=False):
    if with_stdout:
        # Somehow send `msg` through `loginstance` so
        # that it goes BOTH to `/var/log/myprogram.log`
        # AND to `stdout`, with identical formatting.
    else:
        # Send only to `/var/log/myprogram.log` by default.
        loginstance.log(level, msg)

我希望使用一个单logging.Logger个实例来管理它,这样如果我想更改格式或其他日志记录行为,我只需要在一个地方执行此操作。

我猜测这涉及对logging.Logger和/或logging.Formatter进行子类化,但我还没弄清楚如何做到这一点。

提前感谢您提出任何建议。

1 个答案:

答案 0 :(得分:0)

我想出了怎么做。它只需要我使用 Dim MondaySheetRow as Range MondaySheetRow = Sheets("Monday").Rows(8) MondaySheetRow.Insert Shift:=xlDown 子类并将额外的参数传递给FileHandler ......

log()

实例化我的记录器时,我这样做......

class MyFileHandler(logging.FileHandler):
    def emit(self, record):
        super().emit(record)
        also_use_stdout = getattr(record, 'also_use_stdout', False)
        if also_use_stdout:
            savestream = self.stream
            self.stream = sys.stdout
            try:
                super().emit(record)
            finally:
                self.stream = savestream

然后,我上面描述的logger = logging.getLogger('myprogram') logger.addHandler(MyFileHandler('/var/log/myprogram.log')) 函数将如下所示:

mylogger

这是有效的,因为传递给可选def mylogger(level, msg, with_stdout=False): loginstance.log(level, msg, extra={'also_use_stdout': with_stdout}) 字典中的log函数的任何内容都会成为最终传递给extra的{​​{1}}对象的属性。