使用Python讀取大文件的方法
背景
最近處理文本文檔時(shí)(文件約2GB大小),出現(xiàn)memoryError錯(cuò)誤和文件讀取太慢的問(wèn)題,后來(lái)找到了兩種比較快Large File Reading 的方法,本文將介紹這兩種讀取方法。
準(zhǔn)備工作
我們談到“文本處理”時(shí),我們通常是指處理的內(nèi)容。Python 將文本文件的內(nèi)容讀入可以操作的字符串變量非常容易。文件對(duì)象提供了三個(gè)“讀”方法: .read()、.readline() 和 .readlines()。每種方法可以接受一個(gè)變量以限制每次讀取的數(shù)據(jù)量,但它們通常不使用變量。 .read() 每次讀取整個(gè)文件,它通常用于將文件內(nèi)容放到一個(gè)字符串變量中。然而.read() 生成文件內(nèi)容最直接的字符串表示,但對(duì)于連續(xù)的面向行的處理,它卻是不必要的,并且如果文件大于可用內(nèi)存,則不可能實(shí)現(xiàn)這種處理。下面是read()方法示例:
try: f = open('/path/to/file', 'r') print f.read() finally: if f: f.close()
調(diào)用read()會(huì)一次性讀取文件的全部?jī)?nèi)容,如果文件有10G,內(nèi)存就爆了,所以,要保險(xiǎn)起見(jiàn),可以反復(fù)調(diào)用read(size)方法,每次最多讀取size個(gè)字節(jié)的內(nèi)容。另外,調(diào)用readline()可以每次讀取一行內(nèi)容,調(diào)用readlines()一次讀取所有內(nèi)容并按行返回list。因此,要根據(jù)需要決定怎么調(diào)用。
如果文件很小,read()一次性讀取最方便;如果不能確定文件大小,反復(fù)調(diào)用read(size)
比較保險(xiǎn);如果是配置文件,調(diào)用readlines()最方便:
for line in f.readlines(): process(line) #
分塊讀取
處理大文件是很容易想到的就是將大文件分割成若干小文件處理,處理完每個(gè)小文件后釋放該部分內(nèi)存。這里用了iter 和 yield:
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) # <do something with chunk>
使用With open()
with語(yǔ)句打開(kāi)和關(guān)閉文件,包括拋出一個(gè)內(nèi)部塊異常。for line in f文件對(duì)象f視為一個(gè)迭代器,會(huì)自動(dòng)的采用緩沖IO和內(nèi)存管理,所以你不必?fù)?dān)心大文件。
代碼如下:
#If the file is line based with open(...) as f: for line in f: process(line) # <do something with line>
優(yōu)化
面對(duì)百萬(wàn)行的大型數(shù)據(jù)使用with open 是沒(méi)有問(wèn)題的,但是這里面參數(shù)的不同也會(huì)導(dǎo)致不同的效率。經(jīng)過(guò)測(cè)試發(fā)先參數(shù)為"rb"時(shí)的效率是"r"的6倍。由此可知二進(jìn)制讀取依然是最快的模式。
with open(filename,"rb") as f: for fLine in f: pass
測(cè)試結(jié)果:rb方式最快,100w行全遍歷2.9秒?;灸軡M足中大型文件處理效率需求。如果從rb(二級(jí)制讀取)讀取改為r(讀取模式),慢5-6倍。
結(jié)論
在使用python進(jìn)行大文件讀取時(shí),應(yīng)該讓系統(tǒng)來(lái)處理,使用最簡(jiǎn)單的方式,交給解釋器,就管好自己的工作就行了。同時(shí)根據(jù)不同的需求可以選擇不同的讀取參數(shù)進(jìn)一步獲得更高的性能。
相關(guān)文章
python中的生成器實(shí)現(xiàn)周期性報(bào)文發(fā)送功能
本文主要介紹了python中的生成器實(shí)現(xiàn)周期性報(bào)文發(fā)送功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03flask中獲取各種請(qǐng)求數(shù)據(jù)的常見(jiàn)方法小結(jié)
在 Flask 里,能使用多種方法獲取不同類型的請(qǐng)求數(shù)據(jù),這篇文章為大家詳細(xì)介紹了Flask中常見(jiàn)請(qǐng)求數(shù)據(jù)的獲取方式,有需要的小伙伴可以參考一下2025-06-06pycharm沒(méi)有找到manage?repositories按鈕的解決辦法
這篇文章主要給大家介紹了關(guān)于pycharm沒(méi)有找到manage?repositories按鈕的解決辦法,pycharm是用來(lái)寫python的可視化代碼軟件,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07Python自動(dòng)化辦公之合并多個(gè)Excel
在日常的辦公自動(dòng)化工作中,尤其是處理大量數(shù)據(jù)時(shí),合并多個(gè)?Excel?表格是一個(gè)常見(jiàn)且繁瑣的任務(wù),下面小編就來(lái)為大家介紹一下如何使用Python輕松實(shí)現(xiàn)合并多個(gè)Excel吧2025-02-02python中執(zhí)行shell命令的幾個(gè)方法小結(jié)
這篇文章主要介紹了python中執(zhí)行shell命令的幾個(gè)方法,本文一共給出3種方法實(shí)現(xiàn)執(zhí)行shell命令,需要的朋友可以參考下2014-09-09