Python读写大文件过程有哪些坑要注意
Admin 2022-07-16 群英技术资讯 926 次浏览
今天就跟大家聊聊有关“Python读写大文件过程有哪些坑要注意”的内容,可能很多人都不太了解,为了让大家认识和更进一步的了解,小编给大家总结了以下内容,希望这篇“Python读写大文件过程有哪些坑要注意”文章能对大家有帮助。python读写文件的api都很简单,一不留神就容易踩”坑“。笔者记录一次踩坑历程,并且给了一些总结,希望到大家在使用python的过程之中,能够避免一些可能产生隐患的代码。
随手搜索python读写文件的教程,很经常看到read()与readlines()这对函数。所以我们会常常看到如下代码:
with open(file_path, 'rb') as f: sha1Obj.update(f.read()) or with open(file_path, 'rb') as f: for line in f.readlines(): print(line)
这对方法在读取小文件时确实不会产生什么异常,但是一旦读取大文件,很容易会产生MemoryError,也就是内存溢出的问题。
####Why Memory Error?
我们首先来看看这两个方法:
当默认参数size=-1时,read方法会读取直到EOF,当文件大小大于可用内存时,自然会发生内存溢出的错误。
read([size])方法从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,它范围为字符串对象
同样的,readlines会构造一个list。list而不是iter,所以所有的内容都会保存在内存之上,同样也会发生内存溢出的错误。
该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。
在实际运行的系统之中如果写出上述代码是十分危险的,这种”坑“十分隐蔽。所以接下来我们来了解一下正确用,正确的用法也很简单,依照API之中对函数的描述来进行对应的编码就OK了:
如果是二进制文件推荐用如下这种写法,可以自己指定缓冲区有多少byte。显然缓冲区越大,读取速度越快。
with open(file_path, 'rb') as f: while True: buf = f.read(1024) if buf: sha1Obj.update(buf) else: break
而如果是文本文件,则可以用readline方法或直接迭代文件(python这里封装了一个语法糖,二者的内生逻辑一致,不过显然迭代文件的写法更pythonic )每次读取一行,效率是比较低的。笔者简单测试了一下,在3G文件之下,大概性能和前者差了20%.
with open(file_path, 'rb') as f: while True: line = f.readline() if buf: print(line) else: break with open(file_path, 'rb') as f: for line in f: print(line)
对于python代码的内存占用问题,对于代码进行内存监控十分必要。这里笔者这里推荐两个小工具来检测python代码的内存占用。
####memory_profiler
首先先用pip安装memory_profiler
pip install memory_profiler
memory_profiler是利用python的装饰器工作的,所以我们需要在进行测试的函数上添加装饰器。
from hashlib import sha1 import sys @profile def my_func(): sha1Obj = sha1() with open(sys.argv[1], 'rb') as f: while True: buf = f.read(10 * 1024 * 1024) if buf: sha1Obj.update(buf) else: break print(sha1Obj.hexdigest()) if __name__ == '__main__': my_func()
之后在运行代码时加上** -m memory_profiler**
就可以了解函数每一步代码的内存占用了

依样画葫芦,仍然是通过pip先安装guppy
pip install guppy
之后可以在代码之中利用guppy直接打印出对应各种python类型(list、tuple、dict等)分别创建了多少对象,占用了多少内存。
from guppy import hpy import sys def my_func(): mem = hpy() with open(sys.argv[1], 'rb') as f: while True: buf = f.read(10 * 1024 * 1024) if buf: print(mem.heap()) else: break
如下图所示,可以看到打印出对应的内存占用数据:

通过上述两种工具guppy与memory_profiler可以很好地来监控python代码运行时的内存占用问题。
python是一门崇尚简洁的语言,但是正是因为它的简洁反而更多了许多需要仔细推敲和思考的细节。希望大家在日常工作与学习之中也能多对一些细节进行总结,少踩一些不必要的“坑”。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
定义匿名函数指一类无须定义标识符的函数或子程序。Python用lambda语法定义匿名函数,只需用表达式而无需申明。lambda语法的定义如下:lamb
通过 Python 绘制精美的地图?想在地图上自由的设置各种参数?想获得灵活的交互体验?这里就有一款Python 神包满足你:folium。
最近在进行django项目开发的时候,遇到了需要连接两个MySQL数据库的问题,下面这篇文章主要给大家介绍了关于Django项目配置连接多个数据库的相关资料,需要的朋友可以参考下
Python基础-PEP8 提供了 Python 代码的编写约定. 本节知识点旨在提高代码的可读性, 并使其在各种 Python 代码中编写风格保持一致.
ascii() 函数类似 repr() 函数, 返回一个表示对象的字符串, 但是对于字符串中的非 ASCII 字符则返回通过 repr() 函数使用 \x, \u 或 \U 编码的字符。 生成字符串类似 Python2 版本中 repr() 函数的返回值。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008