以块的形式读取文件 - 使用RAM,从二进制文件读取字符串

xph*_*xph 10 python string ram

我想了解在python中读取大文件时这种方法的RAM使用的差异.

版本1,在stackoverflow上找到:

def read_in_chunks(file_object, chunk_size=1024):
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data


f = open(file, 'rb')
for piece in read_in_chunks(f):
    process_data(piece)          
f.close()
Run Code Online (Sandbox Code Playgroud)

版本2,我在找到上面的代码之前使用了这个:

f = open(file, 'rb')
while True:
    piece = f.read(1024)      
    process_data(piece)        
f.close()
Run Code Online (Sandbox Code Playgroud)

在两个版本中都部分读取该文件.并且可以处理当前的部分.在第二个例子中,piece每个周期都有新的内容,所以我认为这样做不会将完整的文件加载到内存中.

但我真的不明白是什么yield,我很确定我在这里弄错了.有谁可以向我解释一下?


除了使用的方法之外,还有一些令我困惑的事情:

我读取的作品的内容由上面示例中的1KB的块大小定义.但是......如果我需要在文件中查找字符串怎么办?有点像"ThisIsTheStringILikeToFind"

根据String发生在文件中的位置,可能是一件包含该部件"ThisIsTheStr"- 而下一件将包含该部件"ingILikeToFind".使用这种方法,不可能在任何一块中检测整个字符串.

有没有办法以块的形式读取文件 - 但不知何故关心这些字符串?

欢迎任何帮助或想法,

映入眼帘!

AJM*_*eld 19

yield是python中用于生成器表达式的关键字.这意味着下次调用(或迭代)函数时,执行将在上次调用它时从它停止的确切点开始备份.这两个功能的功能相同; 唯一的区别是第一个使用比第二个更多的调用堆栈空间.但是,第一个更可重复使用,因此从程序设计的角度来看,第一个实际上更好.

编辑:另外,另一个区别是,一旦读取了所有数据,第一个将停止读取它应该的方式,但第二个将只停止一次f.read()process_data()抛出异常.为了使第二个正常工作,您需要像这样修改它:

f = open(file, 'rb')
while True:
    piece = f.read(1024)  
    if not piece:
        break
    process_data(piece)
f.close()
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答!我知道第一个版本的可重用性更好,它定义了一个在其他项目中也可能有用的函数。更大的“调用堆栈空间”由此产生,我猜?创建函数?但是文件本身的RAM使用量没有区别吗?我找到了一些关于生成器函数的文档,当你一直记住通用函数时,这并不容易理解 - 但如果我做对了,第一个版本将“返回”文件的第一部分并且 `for` 循环会在没有 `yield` 的情况下循环遍历 `piece` 的数据吗? (2认同)

mar*_*eau 6

我认为最好和最惯用的方法可能是使用内置iter()函数及其可选sentinel参数来创建和使用可迭代对象,如下所示。请注意,如果文件大小不是它的精确倍数,则最后一个块可能小于请求的块大小。

from functools import partial

CHUNK_SIZE = 1024
filename = 'testfile.dat'

with open(filename, 'rb') as file:
    for chunk in iter(partial(file.read, CHUNK_SIZE), b''):
        process_data(chunk)
Run Code Online (Sandbox Code Playgroud)

更新:不知道它是什么时候添加的,但几乎完全相同的是上面的内容现在显示为该iter()函数的官方文档中的示例。


hir*_*ist 5

从 python 3.8 开始,您还可以使用赋值表达式(海象运算符):

with open('file.name', 'rb') as file:
    while chunk := file.read(1024):
        process_data(chunk)
Run Code Online (Sandbox Code Playgroud)

最后一个chunk可能小于CHUNK_SIZE.

asread()b""在读取文件后返回,while循环将终止。

  • 多谢告诉我这个消息!我需要查找这个“海象运算符”,可能有助于了解更多信息。 (2认同)