Python如何读取大文件的“坑”与内存占用检测

  介绍

这篇文章主要介绍Python如何读取大文件的“坑”与内存占用检测,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

Python读写文件的api都很简单,一不留神就容易踩“坑”。下面记录一次踩坑历程,并且给了一些总结,希望到大家在使用Python的过程之中,能够避免一些可能产生隐患的代码。

<强> 1.阅读()与readline()

随手搜索Python读写文件的教程,很经常看读到()与readline()这对函数,所以我们会常常看到如下代码:

with 开放(file_path, & # 39; rb # 39;), as  f:   ,,,sha1Obj.update (f.read ())   或   with 开放(file_path, & # 39; rb # 39;), as  f:   ,,,for  line 拷贝f.readlines ():   ,,,,,,,印刷(线)

这对方法在读取小文件时确实不会产生什么异常,但是一旦读取大文件,很容易会产生MemoryError,也就是内存溢出的问题。

我们首先来看看这两个方法:

当默认参数大?1时,读方法会读取直到EOF,当文件大小大于可用内存时,自然会发生内存溢出的错误。

<强>读方法

阅读([大小])方法从文件当前位置起读取大小个字节,若无参数的大小,则表示读取至文件结束为止,它范围为字符串对象

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

readline方法

该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。

<强> 2。正确的用法

在实际运行的系统之中如果写出上述代码是十分危险的,这种“坑”十分隐蔽。所以接下来我们来了解一下正确用,正确的用法也很简单,依之照API中对函数的描述来进行对应的编码就好了:

如果是二进制文件推荐用如下这种写法,可以自己指定缓冲区有多少字节。显然缓冲区越大,读取速度越快。

with 开放(file_path, & # 39; rb # 39;), as  f:   ,,,while 正确的:   ,,,,,,,buf =, f.read (1024)   ,,,,,,,if  buf:,,,,   ,,,,,,,,,,,sha1Obj.update (buf)   ,,,,,,,其他的:   ,,,,,,,,,,,打破

而如果是文本文件,则可以用readline方法或直接迭代文件(python这里封装了一个语法糖,二者的内生逻辑一致,不过显然迭代文件的写法更预言的)每次读取一行,效率是比较低的。笔者简单测试了一下,在3 g文件之下,大概性能和前者差了20%。

 pip  install  memory_profiler 

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

得到hashlib  import  sha1   import 系统   @profile   def  my_func ():   ,,,sha1Obj =, sha1 ()   ,,,with 开放(sys.argv [1],, & # 39; rb # 39;), as  f:   ,,,,,,,while 正确的:   ,,,,,,,,,,,buf =, f.read (10, *, 1024, *, 1024)   ,,,,,,,,,,,if 缓冲区:   ,,,,,,,,,,,,,,,sha1Obj.update (buf)   ,,,,,,,,,,,其他的:   ,,,,,,,,,,,,,,,休息   ,,,print (sha1Obj.hexdigest ())   if  __name__ ==, & # 39; __main__ # 39;:   ,,,my_func ()

<强>孔雀鱼

依样画葫芦,仍然是通过pip先安装孔雀鱼

pip  install 古比鱼

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

得到guppy  import  hpy   import 系统   def  my_func ():   ,,,mem =, hpy ()   ,,,with 开放(sys.argv [1],, & # 39; rb # 39;), as  f:   ,,,,,,,while 正确的:   ,,,,,,,,,,,buf =, f.read (10, *, 1024, *, 1024)   ,,,,,,,,,,,if 缓冲区:   ,,,,,,,,,,,,,,,印刷(mem.heap ())   ,,,,,,,,,,,其他的:   ,,,,,,,,,,,,,,,打破

Python如何读取大文件的“坑”与内存占用检测