python读GB级大文件 - Shuang0420/Shuang0420.github.io GitHub Wiki

在python中读取文件一般来说有三种“读”的方法:.read()、.readline() 和 .readlines()。对于小文件,调用read()会一次性读取文件的全部内容,调用readline()每次读取一行内容,或者调用readlines()一次读取所有内容并按行返回list,都可以非常方便的实现,然而如果一次性读取GB级的文件,内存很容易就爆了。

今天尝试用python读取2.5GB的文件时就出现了out of memory错误。

[4217343.669075] Out of memory: Kill process 32152 (python) score 565 or sacrifice child

于是总结了两种python读大文件的方法,虽然其实我出错的原因并不是读文件😁


首推with open( )

其实之前有很长一段时间不知道with open()的神奇作用,直到这次遇到问题,才发现它的奇妙之处。原来python中用with语句打开和关闭文件,包括了抛出一个内部块异常,并且,for line in f其实是将文件对象f视为一个迭代器,自动的采用缓冲IO和内存管理,所以不必担心大文件。让系统来处理,其实是最简单的方式,交给解释器,就万事大吉了。

#If the file is line based
with open('...') as f:
    for line in f:
        process(line) # 

Read In Chunks

这是正常情况下大家都会想到的办法,就是将大文件分割成若干小文件处理,处理完每个小文件后释放该部分内存。可以参照之前的这篇文《python提高读文件效率》

https://github.com/Shuang0420/Shuang0420.github.io/wiki/python%E6%8F%90%E9%AB%98%E8%AF%BB%E6%96%87%E4%BB%B6%E6%95%88%E7%8E%87

代码如下

file = open("sample.txt")
while 1:
lines = file.readlines(100000)
if not lines:
    break
for line in lines:
    pass # do something

或者

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) # 

顺便提一下我遇到的问题,因为后面测试需要,我将读取的文件按行存到了list里面,memory使用率一路飙升过50%,这真是作死的节奏……之后我取了前500行做测试,memory始终稳定保持在3.5%,问题解决。

参考链接 http://chenqx.github.io/2014/10/29/Python-fastest-way-to-read-a-large-file/

⚠️ **GitHub.com Fallback** ⚠️