如何在Python 3中重写file.write()?
下面的代码在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 个回答
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)
这样做会对你更有帮助,因为它以更常见的方式使用了简单的继承。
file
对象可以写入字节,但你需要以正确的模式打开文件。
fp = open('file.bin', 'wb') # open in binary mode
fp.write(b"some bytes")
pf.close()
如果你想把字符串写入磁盘,首先需要对它们进行编码。
我看到两个问题。
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
中的不同类。