你如何在Python中子类化文件类型?

时间:2009-07-04 19:07:22

标签: python file subclass

我正在尝试在Python中继承内置的file类,为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属性和方法?

2 个答案:

答案 0 :(得分:12)

调用file.__init__是非常可行的(例如,在'/ dev / null'上),但没有实际用途,因为为了{{1}的目的,你试图覆盖write没有“接受” }}语句 - 当后者在print看到file.writesys.stdout的实际实例时(通过继承你已经这样做了),内部调用真实的file

除了print之外,

write并不需要任何其他方法,因此让您的类继承自object而不是file

如果您需要其他文件方法(例如print并非您正在做的事情),建议您自己实施。

答案 1 :(得分:3)

您也可以避免使用super

class SuperFile(file):

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

你可以用它来写。