read()函数的文件大小限制是多少?

11

在使用Python 3.5加载大文件时,我遇到了一个问题。使用没有参数的read()有时会出现OSError: Invalid argument的错误。然后我尝试只读取文件的一部分,似乎可以正常工作。我已确定它在约2.2GB处开始失败。以下是示例代码:

>>> sys.version
'3.5.1 (v3.5.1:37a07cee5969, Dec  5 2015, 21:12:44) \n[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]'
>>> x = open('/Users/username/Desktop/large.txt', 'r').read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
>>> x = open('/Users/username/Desktop/large.txt', 'r').read(int(2.1*10**9))
>>> x = open('/Users/username/Desktop/large.txt', 'r').read(int(2.2*10**9))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

我还注意到这在 Python 2.7 中不会发生。以下是相同代码在 Python 2.7 中的运行结果:

>>> sys.version
'2.7.10 (default, Aug 22 2015, 20:33:39) \n[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)]'
>>> x = open('/Users/username/Desktop/large.txt', 'r').read(int(2.1*10**9))
>>> x = open('/Users/username/Desktop/large.txt', 'r').read(int(2.2*10**9))
>>> x = open('/Users/username/Desktop/large.txt', 'r').read()
>>>

我正在使用OS X El Capitan 10.11.1操作系统。

这是一个错误吗?还是应该使用另一种方法来读取文件?


我猜文件加载能力主要取决于您的设备在那个时间点有多少可用内存。 - ZdaR
我认为这可能是个问题,但是:A)我有16GB内存,目前只使用了8GB。B)如果我切换到Python2.7,它可以正常工作。 - calico_
从第一个输出片段中显示的内容来看,似乎 >>> x = open('/Users/username/Desktop/large.txt', 'r').read(int(2.1*10**9)) 已经成功执行,因为没有引发 OSError。不同的结果也可能是由于使用了两个不同的编译器来构建 Python 解释器。请参见 LLVM、GCC 4.2 和 Apple LLVM 编译器 3.1 之间的区别 - martineau
是的,2.1 * 10 ** 9 是有效的。我尝试了几个值,但注意到它在2.1和2.2之间某个地方开始失败。 - calico_
1个回答

6

是的,你遇到了一个bug。

好消息是有人发现了这个问题,并已经在Python bug跟踪器中创建了一个问题,参见:Issue24658 - open().write() 在2GB+数据上失败(OS X)。这似乎是平台相关的(只适用于OS X),并且在使用read和/或write时可以重现。显然,在OS X的libc实现中,fread.c的实现方式存在问题,请参见此处

坏消息是它仍然是未解决的(目前处于不活动状态),所以你必须等待直到它被解决。无论如何,如果你对细节感兴趣,仍然可以查看那里的讨论。


作为解决方案,我非常确定你可以通过分块读取并在处理过程中链接这些块来规避这个问题。写入时也同样如此。不幸的是,这可能会奏效。


这份错误报告甚至提到了一个堆栈溢出的帖子!如果没有堆栈溢出,Python会怎样呢? - Jean-François Fabre
3
@Jean-FrançoisFabre可能会更加有bug。 - Dimitris Fasarakis Hilliard

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