如何在Python 3中重写file.write()?

3 投票
3 回答
6361 浏览
提问于 2025-04-16 00:00

下面的代码在Python 2.6上可以正常运行,但在Python 3.x上就不行了:

old_file_write = file.write 

class file():
    def write(self, d):
        if isinstance(d, types.bytes):
            self.buffer.write(d)
        else:
            old_file_write(d)

# ... some code I cannot change or do not want to change
f = open("x")
f.write("...")
f.write(b"...")
sys.stdout.write(b"...")
sys.stdout.write("...")
print(b"...")
print("...")

问题在于,在Python 3.x中,第一行会报错:

NameError: name 'file' is not defined

我该如何让它在Python 3.x上也能工作呢?

实际上,两年过去了,我仍在寻找一个能同时适用于这两个版本(2.5+和3.x)的解决方案。

对于那些还在疑惑我为什么要找这个的人,其实只是为了让一些旧代码(别人的代码,有时候你无法修改的)能够在新版Python上运行。

这不是关于我自己的代码,而是关于如何写一些代码,让它能和不太好的代码和谐共处 :)

3 个回答

0
old_file_write = file.write 

你正在使用 file 类的类级别方法。

old_file_write(d)

这本来就不应该能工作。我觉得你可能还是在错误地复制和粘贴。

我想你可能用了

old_file_write(self,d)

这可能是能工作的。

不过你的做法不是很好。考虑一下这个方法。

class MyKindOfFile( file ):
    def write(self, d):
        if isinstance(d, types.bytes):
            self.buffer.write(d)
        else:
            super( MyFindOfFile, write )(d)

这样做会对你更有帮助,因为它以更常见的方式使用了简单的继承。

0

file对象可以写入字节,但你需要以正确的模式打开文件。

fp = open('file.bin', 'wb') # open in binary mode
fp.write(b"some bytes") 
pf.close()

如果你想把字符串写入磁盘,首先需要对它们进行编码。

3

我看到两个问题。

1: 你的 file 类没有从任何特定的类继承。如果我理解得没错,它应该是 io.TextIOWrapper 的一个子类。

2: 在 Python 2.6 和 3.x 中,types 模块(这需要先导入)没有 bytes 这个元素。推荐的方法是直接使用 bytes

重新整理的代码片段:

import io, sys

class file(io.TextIOWrapper):
    def write(self, d, encoding=sys.getdefaultencoding()):
        if isinstance(d, bytes):
            d = d.decode(encoding)
        super().write(d)

old_stdout = sys.stdout    # In case you want to switch back to it again

sys.stdout = file(open(output_file_path, 'w').detach())  # You could also use 'a', 'a+', 'w+', 'r+', etc.

现在它应该能按照你的要求工作,使用 sys.stdout.write 将内容写入你指定的输出文件。(如果你不想写入磁盘上的文件,而是想写入默认的 sys.stdout 缓冲区,使用 sys.stdout = file(sys.stdout.detach()) 可能会有效。)

请注意,由于 Python 3.x 没有 file 类,而 2.6 有 io 模块,你需要使用 io 模块中的某个类。我上面的代码只是一个示例,如果你想让它更灵活,你需要自己去调整。也就是说,根据你要写入的文件类型或写入模式,你可能需要使用 io 中的不同类。

撰写回答