如何使用Python读取大文件
背景
最近处理文本文档时(文件约2GB大小),出现memoryError
错误和文件读取太慢的问题,后来找到了两种比较快Large File Reading
的方法,本文将介绍这两种读取方法。
准备工作
我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()
、.readline()
和 .readlines()
。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read()
每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而.read()
生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。下面是read()
方法示例:
try:
f = open('/path/to/file', 'r')
print f.read()
finally:
if f:
f.close()
调用read()
会一次性读取文件的全部内容,如果文件有10G,内存就爆了,所以,要保险起见,可以反复调用read(size)
方法,每次最多读取size个字节的内容。另外,调用readline()
可以每次读取一行内容,调用readlines()
一次读取所有内容并按行返回list。因此,要根据需要决定怎么调用。
如果文件很小,read()
一次性读取最方便;如果不能确定文件大小,反复调用read(size)
比较保险;如果是配置文件,调用readlines()
最方便:
for line in f.readlines():
process(line) #
分块读取
处理大文件是很容易想到的就是将大文件分割成若干小文件处理,处理完每个小文件后释放该部分内存。这里用了iter 和 yield
:
def read_in_chunks(filePath, chunk_size=1024*1024):
"""
Lazy function (generator) to read a file piece by piece.
Default chunk size: 1M
You can set your own chunk size
"""
file_object = open(filePath)
while True:
chunk_data = file_object.read(chunk_size)
if not chunk_data:
break
yield chunk_data
if __name__ == "__main__":
filePath = './path/filename'
for chunk in read_in_chunks(filePath):
process(chunk) # <do something with chunk>
使用With open()
with
语句打开和关闭文件,包括抛出一个内部块异常。for line in f
文件对象f
视为一个迭代器,会自动的采用缓冲IO
和内存管理,所以你不必担心大文件。
代码如下:
#If the file is line based
with open(...) as f:
for line in f:
process(line) # <do something with line>
优化
面对百万行的大型数据使用with open 是没有问题的,但是这里面参数的不同也会导致不同的效率。经过测试发先参数为"rb"时的效率是"r"的6倍。由此可知二进制读取依然是最快的模式。
with open(filename,"rb") as f:
for fLine in f:
pass
测试结果:rb方式最快,100w行全遍历2.9秒。基本能满足中大型文件处理效率需求。如果从rb(二级制读取)读取改为r(读取模式),慢5-6倍。
结论
在使用python进行大文件读取时,应该让系统来处理,使用最简单的方式,交给解释器,就管好自己的工作就行了。同时根据不同的需求可以选择不同的读取参数进一步获得更高的性能。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux下Redis允许远程连接的实现方法
- Linux Socket 编程简介和实现
- Linux (Ubuntu 18.04) 下安装vim编辑器的方法
- 把windows下的字体安装到Linux系统下的方法介绍
- Ubuntu 7.10修改软件源的方法
- Linux 僵尸进程产生原因及解决方法
- Ubuntu17.04配置更换国内源的方法
- Centos7硬盘挂载方法
- linux sort多字段排序实例解析
- Linux中Centos7搭建Hadoop服务步骤
- Centos7实现磁盘限额设置方法
- 在CentOS中部署多节点Citus集群的详细步骤
- 建立自己的npm镜像服务器
- Hugo搭建博客(一)— 基本设置
- Canvas系列(1):直线图形