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

时间:2013-06-12 01:29:43

标签: 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()

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

f = open(file, 'rb')
while True:
    piece = f.read(1024)      
    process_data(piece)        
f.close()

在两个版本中部分读取文件。并且可以处理当前的部分。在第二个示例中,piece在每个周期都获得了新内容,所以我认为这样做可以将整个文件加载到内存中。?

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


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

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

这样的东西

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

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

欢迎任何帮助或想法,

迎接!

3 个答案:

答案 0 :(得分:19)

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

编辑:另外,另一个不同之处在于,第一个数据将在读取完所有数据后停止读取,应该是这样,但第二个数据只会在f.read()或{{1}之后停止抛出一个异常。为了使第二个正常工作,您需要像这样修改它:

process_data()

答案 1 :(得分:3)

从python 3.8开始,您还可以使用assignment expression(海象运算符):

with open('file.name', 'rb') as file:
    while chunk := file.read(1024)
        process_data(chunk)

最后一个chunk可能小于CHUNK_SIZE

由于read()将在读取文件后返回b"",因此while循环将终止。

答案 2 :(得分:0)

我认为可能最好的也是最惯用的方法是使用内置的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)