標籤:class pen lines spl 速度 美的 限制 bre 檔案流
在我們日常工作中,難免會有處理記錄檔的時候,當檔案小的時候,基本不用當心什麼,直接用file.read()或readlines()就可以了,但是如果是將一個10G大小的記錄檔讀取,即檔案大於記憶體的大小,這麼處理就有問題了,會將整個檔案載入到記憶體中從而造成MemoryError … 也就是發生記憶體溢出。
下面分享幾個解決辦法:
對file對象進行迭代處理:
with open(‘file_name‘, ‘r‘) as file: for line in file: print line
優點:
with語句,檔案對象在執行完代碼塊退出後自動關閉檔案流,檔案讀取資料發生異常,進行異常捕獲處理
對檔案對象進行迭代時,在內部,它會緩衝IO(針對昂貴的IO操作進行最佳化)和記憶體管理,所以不必擔心大檔案。
這才是 Pythonci
最完美的方式,既高效又快速
缺點:每一行的資料內容不能大於記憶體大小,否則就會造成MemoryError
使用yield
正常情況使用上面這種方式就可以了,But
,如果遇到整個檔案只有一行,而且按照特定的字元進行分割,上面這種方式則不行了,這時候yield就非常有用了。
舉個栗子,log的形式是這樣子的。
2018-06-18 16:12:08,289 - main - DEBUG - Do something{|}…..
以{|}做為分割符。
def read_line(filename, split, size): with open(filename, ‘r+‘) as file: buff = ‘‘ while True: while split in buff: position = buff.index(split) yield buff[:position] buff = buff[(position +len(split)):] chunk = file.read(size) if not chunk: yield buff break buff = buff +chunk
優點:不在限制每行資料的大小,即使整個大檔案只有一行。
缺點:速度比上面這種方式要慢。
解析一下:
首先:定義一個緩衝區buff
迴圈判斷,如果split分割符在緩衝區buff,則進行尋找分割符出現的位置,並yield回去。
將buff更新,繼續第二步
如果split分割符不在緩衝區buff,則read(size)個字元
如果chunk為空白,則跳出迴圈,否則更新buff, 繼續第二步
所以我們需要使用那種方式呢,一般來說使用用第一種就可以了。碰到只有一行的資料,而且資料特別大的,就要考慮一下你是不是得罪那個程式員了,故意給你這樣一個檔案。
在python中逐行讀取大檔案