READAHEAD_BUFSIZE
仅在将文件用作迭代器时使用:
for line in fileobj:
print line
它是一个独立于普通缓冲区参数的缓冲区,由fread
C API 调用处理。迭代时都使用两者。
来自file.next()
:
为了使for
循环成为循环文件行的最有效方式(一种非常常见的操作),该next()
方法使用隐藏的预读缓冲区。作为使用预读缓冲区的结果,next()
与其他文件方法(如readline()
)组合不能正常工作。但是,使用seek()
将文件重新定位到绝对位置将刷新预读缓冲区。
操作系统缓冲区大小没有改变,setvbuf
当文件打开并且文件迭代代码没有触及时完成。相反,调用Py_UniversalNewlineFread
(which uses fread
) 用于填充预读缓冲区,在 Python 内部创建第二个缓冲区。否则,Python 将常规缓冲留给 C API 调用(fread()
调用被缓冲;用户空间缓冲区被咨询fread()
以满足请求,Python 不必对此做任何事情)。
readahead_get_line_skip()
然后从此缓冲区提供行(换行终止)。如果缓冲区不再包含换行符,它将通过以 1.25 倍于前一个值的缓冲区大小递归自身来重新填充缓冲区。这意味着如果整个文件中没有换行符,文件迭代可以将文件的整个其余部分读入内存缓冲区!
要查看缓冲区读取了多少,请fileobj.tell()
在循环时打印文件位置(使用 ):
>>> with open('test.txt') as f:
... for line in f:
... print f.tell()
...
8192 # 1 times the buffer size
8192
8192
~ lines elided
18432 # + 1.25 times the buffer size
18432
18432
~ lines elided
26624 # + 1 times the buffer size; the last newline must've aligned on the buffer boundary
26624
26624
~ lines elided
36864 # + 1.25 times the buffer size
36864
36864
等等
实际从磁盘读取的字节(假设fileobj
是磁盘上的实际物理文件)不仅取决于fread()
缓冲区和内部预读缓冲区之间的相互作用;而且如果操作系统本身正在使用缓冲。很可能即使文件缓冲区已用尽,操作系统也会为系统调用提供服务,以从其自己的缓存中读取文件,而不是转到物理磁盘。