如何在 Python 中对文件类型进行子类化?

发布于 2024-07-26 15:13:14 字数 1609 浏览 1 评论 0原文

我正在尝试对 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 操作已关闭的文件。 我无法在 __init__() 中有意义地调用 file.__init__() ,因为我不想打开新文件,并且无法分配 < code>self.close = False 两者之一,因为它是只读属性。

我如何修改它,以便我可以执行 print 'foo' 操作,并使其支持所有标准 file 属性和方法?

I'm trying to subclass the built-in file class in Python to add some extra features to stdin and stdout. Here's the code I have so far:

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')

The purpose is to add a timestamp to the beginning of each message, and to log everything to a log file. However, the problem I run into is that if I do this:

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

Then when I try to do print 'foo', I get a ValueError: I/O operation on closed file. I can't meaningfully call file.__init__() in my __init__(), since I don't want to open a new file, and I can't assign self.closed = False either, since it's a read-only attribute.

How can I modify this so that I can do print 'foo', and so that it supports all of the standard file attributes and methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甩你一脸翔 2024-08-02 15:13:16

您也可以避免使用 super

class SuperFile(file):

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

您将能够用它来编写。

You can as well avoid using super :

class SuperFile(file):

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

You'll be able to write with it.

流绪微梦 2024-08-02 15:13:15

调用 file.__init__ 是相当可行的(例如,在“/dev/null”上),但没有实际用途,因为您尝试覆盖 write 并没有“采取” print 语句的目的 - 当后者看到 sys.stdout的实际实例时,它会在内部调用真正的 file.write >file (通过继承你就做到了这一点)。

除了write之外,print实际上并不需要任何其他方法,因此使您的类继承自object而不是file将工作。

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

Calling file.__init__ is quite feasible (e.g., on '/dev/null') but no real use because your attempted override of write doesn't "take" for the purposes of print statements -- the latter internally calls the real file.write when it sees that sys.stdout is an actual instance of file (and by inheriting you've made it so).

print doesn't really need any other method except write, so making your class inherit from object instead of file will work.

If you need other file methods (i.e., print is not all you're doing), you're best advised to implement them yourself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文