使用logg时在stderr文件中打印stdout

2024-04-28 15:35:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用logger打印出stdout和stderr到日志文件。我已经做到了:

def log(process):

    logger = logging.getLogger('logging_errors')
    if not len(logger.handlers):
        logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(levelname)s %(asctime)s %(module)s %(message)s')

        handler_stderr = logging.FileHandler('stderr.log')
        handler_stderr.setLevel(logging.WARNING)
        handler_stderr.setFormatter(formatter)
        logger.addHandler(handler_stderr)

        handler_stdout = logging.FileHandler('stdout.log')
        handler_stdout.setLevel(logging.DEBUG)
        handler_stdout.setFormatter(formatter)
        logger.addHandler(handler_stdout)
    return logger.error(process.stderr.read())
    return logger.info(process.stdout.read())

一个过程被传递给这个函数,可以是这样的:

^{pr2}$

我的问题是标准输出不能打印到标准输出日志档案,我把史德瑞带进去标准输出日志文件。标准日志文件正确。有什么线索吗?在


Tags: 文件debuglog标准formatterloggingstderrstdout
2条回答

您可以设置两个记录器,一个用于stdout,另一个用于stderr,但是您必须编写

info_logger.info(out)
error_logger.error(err)

这是重复的,因为你必须同时选择适当的记录器和适当的级别,因为它们都包含基本相同的信息。在

因此,我们可以使用一个稍微有点花哨的人,使用robert's LevelFilter创建一个带有两个过滤处理程序的记录器。每个处理程序都有一个筛选器,仅接受级别小于或等于end_level的日志记录:

^{pr2}$

同时,声明

handler.setLevel(begin_level)

使handler只接受那些级别大于begin_level的日志记录。结合起来,我们有一个处理程序,它只接受那些级别在begin_level和{}之间的日志记录。因此,您可以有一个处理程序处理调试和信息日志记录,另一个处理程序处理警告、错误和关键日志记录。在

综合起来,你可以用这样的方法:

import logging
import subprocess

class LevelFilter(logging.Filter):
    """
    https://stackoverflow.com/a/7447596/190597 (robert)
    """
    def __init__(self, level):
        self.level = level

    def filter(self, record):
        return record.levelno <= self.level

def splitlevel_logger(name, outpath='stderr.log', errpath='stdout.log',
                      fmt='%(levelname)s %(asctime)s %(module)s %(message)s'):
    formatter = logging.Formatter(fmt)
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    for filename, begin_level, end_level in (
            (outpath, logging.WARNING, logging.CRITICAL),
            (errpath, logging.DEBUG, logging.INFO)):
        handler = logging.FileHandler(filename, 'w')
        handler.setLevel(begin_level)
        handler.addFilter(LevelFilter(end_level))
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    return logger

def log(out='', err=''):
    if out:
        logger.info(out)
    if err:
        logger.error(err)

logger = splitlevel_logger(__name__)
cmd = 'FastTree -nt test.fasta'
proc = subprocess.Popen(cmd,
                        stdout = subprocess.PIPE,
                        stderr = subprocess.PIPE, shell=True) 
log(*proc.communicate())

顺便说一下,请注意有关subprocess.Popen.wait的警告:

Warning

[Popen.wait] will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

因此,在上面的情况下使用Popen.wait可能有缺陷。使用Popen.communicate可避免此问题。 或者,如果您想在子进程输出时读取并记录输出(而不是仅在子进程完成后才接收)use threading或{a4}。在

你有

return logger.error(process.stderr.read())
return logger.info(process.stdout.read())

第二条return语句不会执行,因此进程stdout永远不会被记录。只要从这些语句中删除return,您就会发现输出出现在stdout.log中。在

您将在stdout.log中得到stderr输出,因为所有记录的事件都传递给两个处理程序。在

相关问题 更多 >