记录器配置以记录到文件并打印到stdout

时间:2012-12-05 22:22:51

标签: python file logging stdout

我正在使用Python的日志记录模块将一些调试字符串记录到一个非常好的文件中。现在另外,我想使用这个模块也将字符串打印到stdout。我该怎么做呢?为了将我的字符串记录到文件中,我使用以下代码:

import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
    LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

然后调用记录器函数,如

logger.debug("I am written to the file")

感谢您的帮助!

8 个答案:

答案 0 :(得分:361)

只需获取根记录器的句柄并添加StreamHandler即可。 StreamHandler写入stderr。不确定你是否真的需要stdout而不是stderr,但这是我在设置Python记录器时使用的,我也添加了FileHandler。然后我的所有日​​志都会转到这两个地方(这听起来像你想要的那样)。

import logging
logging.getLogger().addHandler(logging.StreamHandler())

如果要输出到stdout而不是stderr,则只需将其指定给StreamHandler构造函数。

import sys
# ...
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

您还可以向其添加Formatter,以便所有日志行都有一个公共标题。

即:

import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

打印格式为:

2012-12-05 16:58:26,618 [MainThread  ] [INFO ]  my message

答案 1 :(得分:139)

logging.basicConfig()可以从Python 3.3开始使用关键字参数handlers,这简化了日志记录设置,尤其是在使用相同的格式化程序设置多个处理程序时:

  

handlers - 如果指定,这应该是已创建的处理程序的可迭代,以添加到根记录器。任何尚未设置格式化程序集的处理程序都将被分配在此函数中创建的默认格式化程序。

因此,接受的答案中相当长且详细的示例代码就变成了这样:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s",
    handlers=[
        logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
        logging.StreamHandler()
    ])

(或根据原始问题的要求使用import sys + StreamHandler(sys.stdout)。)

要获取记录器,请使用

logger = logging.getLogger()

稍后在您的脚本中,使用logger.info()输出有用的日志消息。

答案 2 :(得分:62)

添加不带参数的StreamHandler会转到stderr而不是stdout。如果某个其他进程依赖于stdout转储(即编写NRPE插件时),那么请确保明确指定stdout,否则可能会遇到一些意想不到的麻烦。

这是一个快速示例,重用问题中的假设值和LOGFILE:

import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys

log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)

fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)

答案 3 :(得分:19)

在设置任何其他处理程序或记录任何消息之前,以basicConfig为参数运行stream=sys.stdout,或者手动添加将消息发送到stdout到根记录器的StreamHandler(或者你想要的任何其他记录器。(

答案 4 :(得分:10)

这是一个基于Waterboy's answer和其他各种来源的完整且包装精美的解决方案。它支持同时记录到控制台和日志文件,允许进行不同的日志级别设置,提供彩色输出,并且易于配置(也可以作为Gist使用):

int main() {
    Writer tolstoy("Leo", "Tolstoy", 82);
    Book war_and_peace("War and Peace", 1870);
    tolstoy.addToAuthor(war_and_peace);

    Writer _writer("Writer", "Surname", 18);
    Book book("The Book", 2020);
    _writer.addToAuthor(book);

    tolstoy.printAuthor();

    _writer = tolstoy;

    return 0;
}

有关Microsoft Windows 10的注意事项:
为了使颜色实际出现在Microsoft Windows 10上,必须首先启用ANSI终端模式。这是一个用于执行此操作的函数:

_writer = tolstoy;

答案 5 :(得分:2)

在多个Python包中反复使用Waterboy的代码后,我最终将其转换为一个很小的独立Python包,您可以在这里找到它:

https://github.com/acschaefer/duallog

该代码有据可查且易于使用。只需下载.py文件并将其包含在您的项目中,或通过pip install duallog安装整个软件包。

答案 6 :(得分:1)

以不同的级别和格式登录stdoutrotating file

import logging
import logging.handlers
import sys

if __name__ == "__main__":

    # Change root logger level from WARNING (default) to NOTSET in order for all messages to be delegated.
    logging.getLogger().setLevel(logging.NOTSET)

    # Add stdout handler, with level INFO
    console = logging.StreamHandler(sys.stdout)
    console.setLevel(logging.INFO)
    formater = logging.Formatter('%(name)-13s: %(levelname)-8s %(message)s')
    console.setFormatter(formater)
    logging.getLogger().addHandler(console)

    # Add file rotating handler, with level DEBUG
    rotatingHandler = logging.handlers.RotatingFileHandler(filename='rotating.log', maxBytes=1000, backupCount=5)
    rotatingHandler.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    rotatingHandler.setFormatter(formatter)
    logging.getLogger().addHandler(rotatingHandler)

    log = logging.getLogger("app." + __name__)

    log.debug('Debug message, should only appear in the file.')
    log.info('Info message, should appear in file and stdout.')
    log.warning('Warning message, should appear in file and stdout.')
    log.error('Error message, should appear in file and stdout.')

答案 7 :(得分:-3)

对于2.7,请尝试以下操作:

fh = logging.handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)