Python多进程中的日志记录:AttributeError: 'Logger'对象没有'flush'属性。

12

基于这个code,我创建了一个Python对象,既可以将输出打印到终端,又可以将输出保存到一个日志文件中,并在其名称后附加日期和时间:

import sys
import time

class Logger(object):
    """
    Creates a class that will both print and log any
    output text. See https://dev59.com/7m445IYBdhLWcg3w1tgS#5916874
    for original source code. Modified to add date and
    time to end of file name.
    """
    def __init__(self, filename="Default"):
        self.terminal = sys.stdout
        self.filename = filename + ' ' + time.strftime('%Y-%m-%d-%H-%M-%S') + '.txt'
        self.log = open(self.filename, "a")

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)


sys.stdout = Logger('TestLog')

这很有效,但当我尝试将其与使用Pool多进程函数的脚本一起使用时,会出现以下错误:
AttributeError: 'Logger' object has no attribute 'flush'

如何修改我的Logger对象,使其能够与任何并行运行的脚本一起工作?

3个回答

35

通常情况下,“类似文件”并不意味着它必须实现“flush()”。在几乎所有的上下文中,“类似文件”要么意味着它有一个readline()/read()方法(如果文件是一个输入被读取的话),要么意味着它必须实现write()方法(如果它用于输出内容)。在这种情况下,大多数库都假定sys.stdout是一个真正的文件,因为通常在不替换sys.stdout的情况下执行日志记录。 - Bakuriu
@Bakuriu 有没有更好的方法既记录文本又在终端上打印它? - Michael

0

@ecatmur的回答只会修复缺失的刷新,一旦添加了这个,我会收到:

AttributeError: 'Logger' object has no attribute 'fileno'

原始代码的帖子中有一条评论提供了一个修改方案,可以考虑任何额外缺失的属性,为了完整起见,我将发布这段代码的完整工作版本:
class Logger(object):
    def __init__(self, filename = "logfile.log"):
        self.terminal = sys.stdout
        self.log = open(filename, "a")

    def __getattr__(self, attr):
        return getattr(self.terminal, attr)

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

    def flush(self):
        pass

这在我的Python 2.7中运行没有错误。尚未在3.3+中测试。


0
如果没有实现flush,它将无法工作。下面是一个已经实现了flush的详细答案。
import sys
import logging

class Logger(object):
    def __init__(self, filename):
        self.terminal = sys.stdout
        self.log = open(filename, "a")
    def __getattr__(self, attr):
        return getattr(self.terminal, attr)
    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)      
    def flush(self):
        self.terminal.flush()
        self.log.flush()

我在没有刷新日志的情况下遇到了问题。 然后,可以按如下方式使用:

sys.stdout = Logger("file.log")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接