读取/写入大字节字符串时出现IOError: [Errno 22]无效参数

12

我得到了

IOError: [Errno 22] Invalid argument

当我使用f.write()将一个大的字节串写入磁盘时,出现了错误。这里的f是以wb模式打开的。

我在网上看到很多人在使用Windows网络驱动器时出现了这个错误,但我用的是OSX(10.7当我最初提问时,但现在是10.8,使用标准的HFS+本地文件系统)。我使用的是Python 3.2.2(发生在python.org二进制和homebrew安装中)。但是,在系统Python 2.7.2中,我没有看到这个问题。

我还尝试了以w+b模式进行操作,基于这个Windows bug workaround,但是当然这并没有起到任何帮助。

数据来自一个大型的numpy数组(近4GB的浮点数)。如果我手动循环字符串并按块写出,它可以正常工作。但由于我不能一次性写入所有数据,所以np.savenp.savez失败了——因为它们只是使用f.write(ary.tostring())。当我尝试将其保存到已存在的HDF5文件中时,并使用h5py,也会出现类似的错误。

请注意,如果使用file(filename, 'rb')打开文件进行读取,我也会遇到同样的问题:f.read()会出现IOError,而对于合理的chunk_sizef.read(chunk_size)可以正常工作。

有什么想法吗?


奇怪。EINVAL=22,但man 2 write中似乎没有适用的内容。你能否在dtruss下运行以检查是否真的是write系统调用失败了? - ephemient
如果我手动循环字符串并分块写出,它可以正常工作。那你为什么不这样做呢?你认为一次应该能够写入多大的数据块?难道比size_t还要大吗? - msw
2
@msw 就像我说的那样,这会破坏 np.save,对我来说更重要的是 h5py。显然,如果我手动操作,我可以并且确实会将其分成块,并且如果我先创建数据集,然后每次写入50行,它在 h5py 中可以正常工作。但是这不应该是必要的,因为这两个库都没有看到这种需要。而我的数组仅有“500 million entries”(log_2 < 29),这可以由32位 int,更不用说 size_t 来寻址。 - Danica
可能与此无关,但在Linux上有MAX_RW_COUNT(单个read()/write()系统调用不会读取/写入超过该值),在某些情况下最小为2147479552。 - jfs
你能否创建一个文件包装器,将大的读写请求“分块”成多个足够小的部分,以避免这个问题? - martineau
显示剩余3条评论
2个回答

7
这似乎是一个与fread / fwrite有关的OSX通用bug,因此无法由Python用户修复。请参见numpy #3858this torch7 committhis SO question/answer,...。
据说在Mavericks中已经修复了这个问题,但我仍然遇到了这个问题。
Python 2可能已经解决了这个问题,或者它的io模块可能一直缓冲大量的读写; 我没有进行彻底调查。

-2
也许尝试不要使用 b 标志打开文件,因为我认为并不是所有的操作系统/文件系统都支持它。

b标志对于二进制模式是必需的,这意味着在Python 3中它处理字节而不是字符串。你可能想到的是,在Python 2中,b在Unix平台上是一个无操作符,但这种情况已经不再存在了。 - Danica
另外,只是为了确保,我刚刚尝试了一下(使用模式w打开文件并执行f.write(the_bytestring.decode('latin1'))来输出基于真实字节串的乱码),结果得到相同的IOError 22错误。 - Danica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接