python读取大文件的几种方法
在python中,当我们读取一个本地TextIO文件时,最常用的方式是用read
、readline
和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
利用迭代器
和生成器
构造一个可复用的分块读取方法,然后就可以方便的控制每次读取的字节大小,在内存的占用以及代码的执行性能上都会有不错的表现。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: