13

file我正在尝试对Python 中的内置类进行子类化,以向stdinstdout. 这是我到目前为止的代码:

class TeeWithTimestamp(file):
    """
    Class used to tee the output of a stream (such as stdout or stderr) into
    another stream, and to add a timestamp to each message printed.
    """

    def __init__(self, file1, file2):
        """Initializes the TeeWithTimestamp"""
        self.file1 = file1
        self.file2 = file2
        self.at_start_of_line = True

    def write(self, text):
        """Writes text to both files, prefixed with a timestamp"""

        if len(text):
            # Add timestamp if at the start of a line; also add [STDERR]
            # for stderr
            if self.at_start_of_line:
                now = datetime.datetime.now()
                prefix = now.strftime('[%H:%M:%S] ')
                if self.file1 == sys.__stderr__:
                    prefix += '[STDERR] '
                text = prefix + text

            self.file1.write(text)
            self.file2.write(text)

            self.at_start_of_line = (text[-1] == '\n')

目的是在每条消息的开头添加时间戳,并将所有内容记录到日志文件中。但是,我遇到的问题是,如果我这样做:

# log_file has already been opened
sys.stdout = TeeWithTimestamp(sys.stdout, log_file)

然后当我尝试做时print 'foo',我得到一个ValueError: I/O operation on closed file. 我不能有意义地调用file.__init__()我的__init__(),因为我不想打开一个新文件,我也不能分配self.closed = False,因为它是一个只读属性。

我怎样才能修改它以便我可以这样做print 'foo',并使其支持所有标准file属性和方法?

4

2 回答 2

12

调用file.__init__是非常可行的(例如,在'/dev/null'上),但没有真正的用处,因为您尝试的覆盖write并没有“接受”print语句的目的——后者file.write在看到它sys.stdout是实际的时在内部调用 real的实例file(并且通过继承你已经做到了)。

print除了 之外,实际上不需要任何其他方法write,因此让您的类继承 fromobject而不是file将起作用。

如果您需要其他文件方法(即,print这不是您所做的全部),最好建议您自己实现它们。

于 2009-07-04T19:17:03.017 回答
3

您也可以避免使用super

class SuperFile(file):

    def __init__(self, *args, **kwargs):
        file.__init__(self, *args, **kwargs)

你可以用它来写。

于 2010-03-20T17:55:21.543 回答