当前位置:   article > 正文

Python 读取大文件_python读取大文件

python读取大文件

读取大文件

python读取文件一般情况是利用open()函数以及read()函数来完成:

  1. f = open(filename,'r')
  2. f.read()

这种方法读取小文件,即读取大小远远小于内存的文件显然没有什么问题。但是如果是将一个10G大小的日志文件读取,即文件大小大于内存,这么处理就有问题了,会造成MemoryError … 也就是发生内存溢出。

这里发现跟read()类似的还有其他的方法:read(参数)、readline(参数)、readlines(参数)

read(参数):

read() 方法用于从文件读取指定的字符数(文本模式 t)或字节数(二进制模式 b),如果未给定参数 size 或 size 为负数则读取文件所有内容

  1. while True:
  2.     block = f.read(1024)
  3.     if not block:
  4.         break

readline(参数):

readline() 方法用于从文件读取整行,包括 "\n" 字符。如果指定了一个非负数的参数,则返回指定大小的字节数,包括 "\n" 字符。

  1. while True:
  2.     line = f.readline()
  3.     if not line:
  4.         break

readlines(参数):

readlines() 方法用于读取所有行(直到结束符 EOF)并返回列表,该列表可以由 Python 的 for... in ... 结构进行处理。 如果碰到结束符 EOF 则返回空字符串。

读取全部的行,构成一个list,通过list来对文件进行处理,但是这种方式依然会造成MemoyError

  1. for line in f.readlines():
  2.     ....

分块读取:

处理大文件是很容易想到的就是将大文件分割成若干小文件处理,处理完每个小文件后释放该部分内存。这里用了iter 和 yield:

  1. def read_in_chunks(filePath, chunk_size=1024*1024):
  2.     """
  3.     Lazy function (generator) to read a file piece by piece.
  4.     Default chunk size: 1M
  5.     You can set your own chunk size
  6.     """
  7.     file_object = open(filePath)
  8.     while True:
  9.         chunk_data = file_object.read(chunk_size)
  10.         if not chunk_data:
  11.             break
  12.         yield chunk_data
  13. if __name__ == "__main__":
  14.     filePath = './path/filename'
  15.     for chunk in read_in_chunks(filePath):
  16.         process(chunk) # <do something with chunk>

使用With open():
with语句打开和关闭文件,包括抛出一个内部块异常。for line in f文件对象f视为一个迭代器,会自动的采用缓冲IO和内存管理,所以你不必担心大文件

  1. # If the file is line based
  2. with open(...) as f:
  3.   for line in f:
  4.     process(line) # <do something with line>

关于with open()的优化:
面对百万行的大型数据使用with open 是没有问题的,但是这里面参数的不同也会导致不同的效率。经过测试发先参数为”rb”时的效率是”r”的6倍。由此可知二进制读取依然是最快的模式。

  1. with open(filename,"rb") as f: 
  2.   for fLine in f: 
  3.     pass 

测试结果:rb方式最快,100w行全遍历2.9秒。基本能满足中大型文件处理效率需求。如果从rb(二级制读取)读取改为r(读取模式),慢5-6倍。

内存检测工具介绍

memory_profiler

首先先用pip安装memory-profiler

pip install memory-profiler

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

  1. from hashlib import sha1
  2. import sys
  3. @profile
  4. def my_func():
  5.     sha1Obj = sha1()
  6.     with open(sys.argv[1], 'rb') as f:
  7.         while True:
  8.             buf = f.read(1024 * 1024)
  9.             if buf:
  10.                 sha1Obj.update(buf)
  11.             else:
  12.                 break
  13.     print(sha1Obj.hexdigest())
  14. if __name__ == '__main__':
  15.     my_func()

之后在运行代码时加上-m memory_profiler

就可以了解函数每一步代码的内存占用了。例如下图:


guppy

 

首先,通过pip先安装guppy3

pip install guppy3

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

  1. from guppy import hpy
  2. import sys
  3. def my_func():
  4.     mem = hpy()
  5.     with open(sys.argv[1], 'rb') as f:
  6.         while True:
  7.             buf = f.read(10 * 1024 * 1024)
  8.             if buf:
  9.                 print(mem.heap())
  10.             else:
  11.                 break

 

通过上述两种工具guppy与memory-profiler可以很好地来监控python代码运行时的内存占用问题。

也可以使用mem_top或者pyrasite。有兴趣的可以看一下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/183086
推荐阅读
相关标签
  

闽ICP备14008679号