bug还是特性:open和io.open不可互换
我一直以为 open
和 io.open
是可以互换使用的。
但如果我相信这段代码的话,似乎并不是这样:
import ctypes, io
class POINT(ctypes.Structure):
_fields_ = [("x", ctypes.c_int),("y", ctypes.c_int)]
# THIS WORKS
with open("mypoints.bin", "wb") as f:
for i in range(10):
p = POINT(i,10-i)
print p.x, p.y
f.write(p)
# THIS FAILS
with io.open("mypoints.bin", "wb") as f:
for i in range(10):
p = POINT(i,10-i)
print p.x, p.y
f.write(p)
0 10
Traceback (most recent call last):
File "D:\test.py", line 10, in <module>
f.write(p)
File "c:\Python26\lib\io.py", line 1070, in write
self._write_buf.extend(b)
TypeError: 'POINT' object is not iterable
注意:我是在 Python 2.6.6 版本中测试的。
1 个回答
7
是的,这确实是个“bug”。在Python 2.6中,io.open
有点问题。它本来是想和3.x版本的open
一样好用,以便大家能更顺利地过渡,但在某些情况下它的表现并不正确。比如,它不支持像你提到的那种有缓冲区接口的对象。在Python 2.7中,这个问题被修复了,内置的open
可以像3.x中的open
一样使用,而io.open
只是它的一个别名。
如果你需要以二进制模式打开文件,直接用open
就可以,它在2.x和3.x中的表现是一样的,唯一的区别是,在2.x中,它会接受一些不该写入的对象(比如unicode
对象)。如果你需要以文本模式打开文件,可以用codecs.open
或者带有encoding
参数的io.open
。这两者在3.x中都是可以用的。
不过要注意的是,open
和io.open
并不是可以随便替换的,因为io
是Python 3的io
模块,而在Python 3中,open
和Python 2.6及更早版本的open
是非常不同的。