python读取大文件的几种方法


在 python 中,当我们读取一个本地 TextIO 文件时,最常用的方式是用 readreadline 和 readlines 这三个方法。

fp.readlines()

with open(fp_name) as f_read: data = f_read.readlines() # The type of data is a list. # output: # ["<?xml version='1.0' encoding='utf8'?>\n", ...]

这种方式是将文件里面所有内容按行读取到一个大列表中。对于小文件,这种方式其实挺方便,但对于大文件就会出现内存可能不足的情况,报 MemoryError 错误,或者消耗掉很客观的内存资源。

fp.readline()

# 第一种写法 with open(fp_name) as f_read: while True: line = f_read.readline() # The type of line is a string. if not line: break # 第二种写法 with open(fp_name) as f_read: for line in f_read: ...

上面两种写法本质其实一样,都是按行读取文本,这种方式读取文件会大大减少内存的消耗,一直读到空行或者 EOF 标识才会被终止。一般大场景读取文件这种方式性能和内存消耗比较好。

但这种方式也有一个缺陷,若文本是写在一行,而不是多行,那么这两种写法不论哪一种,都和前面两种方式一样,将所有的文本内容【一行字符串】加载到内存当中,消耗大量的资源。那么这个时候处理单行十分大的文件,使用 fp.read() 这个最为底层的方法更好一些。

fp.read()

with open(fp_name) as f_read: data = f_read.read() # The type of data is a string. # output # '<?xml version=\'1.0\' encoding=\'utf8\'?>\n<OpenDRIVE><header revMajor="1" revMinor="4" name="" version="1.00" date="01/01/1970 17:45\n...\n'

不带参数的情况下,这种方式将文本内容读取为一个大的字符串对象,类似 readlines() 方法,只不过是输出数据的格式不同。如果文本比较大,该方式会消耗很客观的内存。

不过该方法有一个 size 参数,用于设置读取文本的字节数,每次调用 fp.read (size) 会直接返回从当前位置往后读取 size 大小的文件内容,不必等待任何换行符出现,这种方式有利于对单行大文本进行读取处理。

我们可以使用这个分块参数这么读取大文件,效果要比按行读取的方式在内存消耗上优化很多:

from functools import partial, wraps from typing import TextIO, Callable def chunked_file_reader(fp: TextIO, block_size: int=1024 * 8): for chunk in iter(partial(fp.read, block_size), ''): yield chunk def read_file(file_path: str) -> int: count: int = 0 with open(file_path) as f_read: for chunk in chunked_file_reader(f_read): count += 1 print(chunk) return count

利用迭代器生成器构造一个可复用的分块读取方法,然后就可以方便的控制每次读取的字节大小,在内存的占用以及代码的执行性能上都会有不错的表现。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM