我在查找如何计算文件中的行数时发现了这个函数,但我不知道它是如何工作的。
def _count_generator(reader):
b = reader(1024 * 1024)
while b:
yield b
b = reader(1024 * 1024)
with open('test.txt', 'rb') as fp:
c_generator = _count_generator(fp.raw.read)
# count each new line
count = sum(buffer.count(b'\n') for buffer in c_generator)
print('total lines', count + 1)
我知道它将其作为字节对象读取,但我不知道读取器(1024 * 1024)做什么,也不知道整个过程究竟是如何工作的
任何帮助都很感激谢谢.
2条答案
按热度按时间jm2pwxwz1#
open()
返回一个文件对象。因为它使用rb
(读二进制)打开文件,所以它返回一个io.BufferedReader
。底层的原始缓冲区可以通过.raw
属性检索,该属性是一个RawIOBase
-它的方法RawIOBase.read
被传递给_count_generator
。由于
_count_generator
是generator,它是一个可迭代对象,其目的是读取文件中1 mb的数据,并在每次调用时将该数据返回给调用者,直到文件结束-当缓冲区b
结束时,reader()
返回0字节,停止循环。调用者使用这1 mb的数据,并通过
sum
函数一遍又一遍地计算其中新行的数量,直到文件用尽为止。tl;dr你正在一次阅读一个1 mb的文件,并对它的换行符求和。为什么?因为很可能你无法打开整个文件,因为它太大了,无法在内存中一次打开。
ttcibm8c2#
让我们从函数的参数开始。
fp.raw.read
是raw
读取器读取二进制文件fp
的read
方法。read
方法接受一个整数,告诉它要读取多少字节。它在EOF时返回一个空的bytes
。该函数本身是一个生成器。它会延迟调用
read
,一次最多获取1MB的数据。只有在sum
中的生成器发出请求后,才会读取块,sum
中的生成器会计算换行符。带正整数参数的原始读取只会调用底层操作系统一次,因此1MB在本例中只是一个提示:大多数情况下,它将读取一个磁盘块,通常大约为4KB左右。如果您花时间阅读文档,这个程序有两个显而易见的缺陷。
raw
不一定存在于python的每个实现中:这不是
BufferedIOBase
API的一部分,在某些实现中可能不存在。1.非阻塞模式下的
read
可以在没有数据可用但未到达EOF时返回None
。只有空字节表示EOF,因此while
循环应为while b != b'':
。