python 有人能解释一下这个功能是怎么工作的吗

pgvzfuti  于 2023-02-18  发布在  Python
关注(0)|答案(2)|浏览(113)

我在查找如何计算文件中的行数时发现了这个函数,但我不知道它是如何工作的。

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)做什么,也不知道整个过程究竟是如何工作的
任何帮助都很感激谢谢.

jm2pwxwz

jm2pwxwz1#

open()返回一个文件对象。因为它使用rb(读二进制)打开文件,所以它返回一个io.BufferedReader。底层的原始缓冲区可以通过.raw属性检索,该属性是一个RawIOBase-它的方法RawIOBase.read被传递给_count_generator
由于_count_generatorgenerator,它是一个可迭代对象,其目的是读取文件中1 mb的数据,并在每次调用时将该数据返回给调用者,直到文件结束-当缓冲区b结束时,reader()返回0字节,停止循环。
调用者使用这1 mb的数据,并通过sum函数一遍又一遍地计算其中新行的数量,直到文件用尽为止。
tl;dr你正在一次阅读一个1 mb的文件,并对它的换行符求和。为什么?因为很可能你无法打开整个文件,因为它太大了,无法在内存中一次打开。

ttcibm8c

ttcibm8c2#

让我们从函数的参数开始。fp.raw.readraw读取器读取二进制文件fpread方法。read方法接受一个整数,告诉它要读取多少字节。它在EOF时返回一个空的bytes
该函数本身是一个生成器。它会延迟调用read,一次最多获取1MB的数据。只有在sum中的生成器发出请求后,才会读取块,sum中的生成器会计算换行符。带正整数参数的原始读取只会调用底层操作系统一次,因此1MB在本例中只是一个提示:大多数情况下,它将读取一个磁盘块,通常大约为4KB左右。
如果您花时间阅读文档,这个程序有两个显而易见的缺陷。

  1. raw不一定存在于python的每个实现中:
    这不是BufferedIOBase API的一部分,在某些实现中可能不存在。
    1.非阻塞模式下的read可以在没有数据可用但未到达EOF时返回None。只有空字节表示EOF,因此while循环应为while b != b'':

相关问题