Python语言读取大文件的"坑“与内存占用检测
曹宇苗 2018-12-17 来源 : 阅读 245 评论 0

摘要:本文主要向大家介绍了Python语言读取大文件的"坑“与内存占用检测,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

本文主要向大家介绍了Python语言读取大文件的"坑“与内存占用检测,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

1.read()与readlines():

随手搜索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,当文件大小大于可用内存时,自然会发生内存溢出的错误。

同样的,readlines会构造一个list。list而不是iter,所以所有的内容都会保存在内存之上,同样也会发生内存溢出的错误。

2.正确的用法:

在实际运行的系统之中如果写出上述代码是十分危险的,这种”坑“十分隐蔽。所以接下来我们来了解一下正确用,正确的用法也很简单,依照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:
            breakwith open(file_path, 'rb') as f:    for line in f:
        print(line)

3.内存检测工具的介绍:

对于python代码的内存占用问题,对于代码进行内存监控十分必要。这里笔者这里推荐两个小工具来检测python代码的内存占用。

####memory_profiler
首先先用pip安装memory_profiler

pip install memory_profiler

memory_profiler是利用python的装饰器工作的,所以我们需要在进行测试的函数上添加装饰器。

from hashlib import sha1import sys@profiledef 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**
就可以了解函数每一步代码的内存占用了

guppy

依样画葫芦,仍然是通过pip先安装guppy

pip install guppy

之后可以在代码之中利用guppy直接打印出对应各种python类型(list、tuple、dict等)分别创建了多少对象,占用了多少内存。

from guppy import hpyimport sysdef 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代码运行时的内存占用问题。

4.小结:

python是一门崇尚简洁的语言,但是正是因为它的简洁反而更多了许多需要仔细推敲和思考的细节。希望大家在日常工作与学习之中也能多对一些细节进行总结,少踩一些不必要的“坑”。

本文由职坐标整理并发布,希望对同学们学习Python有所帮助,更多内容请关注职坐标编程语言Python频道!

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

一枚资深数据分析师

  • 20
    文章
  • 2226
    人气
  • 71%
    受欢迎度

已有7人表明态度,71%喜欢该老师!

进入TA的空间
名师指导 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
Python爬虫实战之爬虫入门
经验技巧 100% 的用户喜欢
选择先学Python语言还是java对于快速入门大数据有影响吗
经验技巧 100% 的用户喜欢
10分钟区分Python语言中的list、array、matrix
经验技巧 0% 的用户喜欢
盘点Python语言常用模块
经验技巧 0% 的用户喜欢
Python语言入门之内存管理方式和垃圾回收算法解析
经验技巧 0% 的用户喜欢
其他海同名师 更多>>
刘新华
刘新华 联系TA
实力型。激情饱满,对专业充满热情
吴翠红
吴翠红 联系TA
独创“教、学、练、测”循环教学模式
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
黄泽民
黄泽民 联系TA
擅长javase核心技术
程钢
程钢 联系TA
擅长大型企业商业网站开发和管理
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:13167058313
小职老师的微信号:13167058313

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    ICP许可  沪B2-20190160

站长统计