在处理GB级别甚至更大的文件时,一次性将文件内容加载到内存中会引发内存溢出错误,分块读取是处理这类大文件的核心思路,通过每次只读取固定大小的内容块,既能完成文件处理,又能控制内存占用。下面介绍几种Python中实现大文件分块读取的常用思路。

基于文件对象的read方法分块读取
Python的文件对象自带read(size)方法,该方法可以指定每次读取的字节数,当读取到文件末尾时会返回空字符串,利用这个特性可以很方便地实现分块读取。
实现步骤如下:
- 使用
open函数以二进制模式打开文件,二进制模式可以避免编码问题,适配所有类型的文件 - 循环调用
read方法,传入预设的块大小,比如每次读取1024*1024字节也就是1MB - 判断读取到的内容是否为空,为空则说明已经到达文件末尾,退出循环
- 对每个读取到的块进行对应的业务处理,比如计算哈希、写入新文件等
对应的代码示例如下:
def chunk_read_by_read(file_path, chunk_size=1024*1024):
# chunk_size默认为1MB
with open(file_path, 'rb') as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
# 这里写块的处理逻辑,比如打印块大小
print(f"当前块大小:{len(chunk)}字节")
# 如果需要处理文本内容,可以在这里解码,注意指定编码避免报错
# text_chunk = chunk.decode('utf-8', errors='ignore')
if __name__ == '__main__':
# 测试读取当前目录下的test.bin文件,没有的话可以先生成一个
chunk_read_by_read('test.bin')
基于迭代器实现分块读取
可以将分块读取的逻辑封装成生成器函数,这样每次调用生成器就能获取一个文件块,使用起来更灵活,也符合Python的迭代器使用习惯。
生成器实现的优势在于可以延迟生成内容,不需要提前把所有块都存到列表中,进一步节省内存。实现逻辑和上面的read方法类似,只是通过yield关键字返回每个块。
代码示例如下:
def chunk_iterator(file_path, chunk_size=1024*1024):
with open(file_path, 'rb') as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
return
yield chunk
def process_file_by_iterator(file_path):
for chunk in chunk_iterator(file_path):
# 处理每个块的逻辑
print(f"迭代器获取到块大小:{len(chunk)}字节")
if __name__ == '__main__':
process_file_by_iterator('test.bin')
按行分块读取文本大文件
如果是处理文本类型的大文件,很多时候需要按行来处理内容,这时候可以使用readline方法,或者直接使用文件对象的迭代特性,逐行读取内容,本质上也是分块读取的一种形式,块的大小就是每一行的长度。
这种方式不需要指定固定的块大小,适合行结构清晰的文本文件,比如日志文件、CSV文件等。代码示例如下:
def read_large_text_file_by_line(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
# 文件对象本身是可迭代的,逐行返回内容
for line in f:
# 去除行尾的换行符
line = line.rstrip('n')
# 处理单行逻辑
print(f"当前行长度:{len(line)}")
if __name__ == '__main__':
read_large_text_file_by_line('test.txt')
不同实现方式的适用场景对比
不同的分块读取方式有不同的适用场景,下面是几种方式的对比:
| 实现方式 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| read方法分块 | 二进制文件、需要固定大小块的场景 | 块大小可控,逻辑简单 | 需要手动控制循环逻辑 |
| 迭代器分块 | 需要灵活调用、嵌入其他逻辑的场景 | 使用方便,符合Python迭代习惯,内存占用低 | 需要理解生成器的使用逻辑 |
| 按行分块 | 文本文件、按行处理的场景 | 无需指定块大小,适配文本结构 | 只适合文本文件,块大小不固定 |
注意事项
在使用分块读取时需要注意几个问题:
- 块大小的选择需要根据实际内存情况调整,一般设置为1MB到10MB之间比较合适,过小会增加IO次数,过大还是会占用较多内存
- 处理二进制文件时一定要用
rb模式打开,处理文本文件时指定正确的编码,避免乱码问题 - 如果需要在处理块的过程中记录进度,可以通过
tell方法获取当前文件指针的位置,计算已经处理的比例
分块读取是解决大文件处理内存问题的核心方案,开发者可以根据文件的类型和业务需求选择合适的实现思路,在保证功能正常的前提下优化内存占用。