bug还是特性:open和io.open不可互换

5 投票
1 回答
1343 浏览
提问于 2025-04-16 11:13

我一直以为 openio.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中都是可以用的。

不过要注意的是,openio.open并不是可以随便替换的,因为io是Python 3的io模块,而在Python 3中,open和Python 2.6及更早版本的open是非常不同的。

http://docs.python.org/library/io.html

撰写回答