Python讀取大檔案的 坑「與記憶體占用檢測

2021-08-26 05:19:40 字數 3204 閱讀 5164

python讀寫檔案的api都很簡單,一不留神就容易踩」「。筆者記錄一次踩坑歷程,並且給了一些總結,希望到大家在使用python的過程之中,能夠避免一些可能產生隱患的**。

隨手搜尋python讀寫檔案的教程,很經常看到read()與readlines()這對函式。所以我們會常常看到如下**:

with open(file_path, 'rb') as f:

sha1obj.update(f.read())

or

with open(file_path, 'rb') as f:

for line in f.readlines():

print(line)

這對方法在讀取小檔案時確實不會產生什麼異常,但是一旦讀取大檔案,很容易會產生memoryerror,也就是記憶體溢位的問題。

####why memory error?

我們首先來看看這兩個方法:

當預設引數size=-1時,read方法會讀取直到eof,當檔案大小大於可用記憶體時,自然會發生記憶體溢位的錯誤。

同樣的,readlines會構造乙個list。list而不是iter,所以所有的內容都會儲存在記憶體之上,同樣也會發生記憶體溢位的錯誤。

在實際執行的系統之中如果寫出上述**是十分危險的,這種」坑「十分隱蔽。所以接下來我們來了解一下正確用,正確的用法也很簡單,依照api之中對函式的描述來進行對應的編碼就ok了:

如果是二進位制檔案推薦用如下這種寫法,可以自己指定緩衝區有多少byte。顯然緩衝區越大,讀取速度越快。

with open(file_path, 'rb') as f:

while true:

buf = f.read(1024)

if buf:

sha1obj.update(buf)

else:

break

而如果是文字檔案,則可以用readline方法或直接迭代檔案(python這裡封裝了乙個語法糖,二者的內生邏輯一致,不過顯然迭代檔案的寫法更pythonic)每次讀取一行,效率是比較低的。筆者簡單測試了一下,在3g檔案之下,大概效能和前者差了20%.

with open(file_path, 'rb') as f:

while true:

line = f.readline()

if buf:

print(line)

else:

break

with open(file_path, 'rb') as f:

for line in f:

print(line)

對於python**的記憶體占用問題,對於**進行記憶體監控十分必要。這裡筆者這裡推薦兩個小工具來檢測python**的記憶體占用。

####memory_profiler

首先先用pip安裝memory_profiler

pip install memory_profiler
memory_profiler是利用python的裝飾器工作的,所以我們需要在進行測試的函式上新增裝飾器。

from hashlib import sha1

import sys

@profile

def my_func():

sha1obj = sha1()

with open(sys.argv[1], 'rb') as f:

while true:

buf = f.read(10 * 1024 * 1024)

if buf:

sha1obj.update(buf)

else:

break

print(sha1obj.hexdigest())

if __name__ == '__main__':

my_func()

之後在執行**時加上** -m memory_profiler**

就可以了解函式每一步**的記憶體占用了

依樣畫葫蘆,仍然是通過pip先安裝guppy

pip install guppy
之後可以在**之中利用guppy直接列印出對應各種python型別(list、tuple、dict等)分別建立了多少物件,占用了多少記憶體。

from guppy import hpy

import sys

def my_func():

mem = hpy()

with open(sys.argv[1], 'rb') as f:

while true:

buf = f.read(10 * 1024 * 1024)

if buf:

print(mem.heap())

else:

break

如下圖所示,可以看到列印出對應的記憶體占用資料:

通過上述兩種工具guppy與memory_profiler可以很好地來監控python**執行時的記憶體占用問題。

python是一門崇尚簡潔的語言,但是正是因為它的簡潔反而更多了許多需要仔細推敲和思考的細節。希望大家在日常工作與學習之中也能多對一些細節進行總結,少踩一些不必要的「坑」。

python讀取大檔案的方法及mmap記憶體對映模組

python計算檔案的行數和讀取某一行內容的實現方法 最簡單的辦法是把檔案讀入乙個大的列表中,然後統計列表的長度.如果檔案的路徑是以引數的形式filepath傳遞的,那麼只用一行 就可以完成我們的需求了 使用python內建的模組mmap可以處理大檔案 注意 mmap在mac下的支援不是很好,有些函...

python 讀取大檔案

以前一直沒有關注過python讀取大檔案的問題,因為一直都是順順暢暢地讀取了檔案。直到今天有人問我python怎麼讀取檔案出現了記憶體不足的錯誤?我才發現原來大檔案 gb級別 的讀取和普通檔案的讀取是不一樣的。下面介紹三種我親測可用的方法。這裡的檔案型別可以是txt,dat等型別的檔案。用read ...

python讀取大檔案

最近在學習python的過程中接觸到了python對檔案的讀取。python讀取檔案一般情況是利用open 函式以及read 函式來完成 f open filename,r f.read 這種方法讀取小檔案,即讀取遠遠大小小於記憶體的檔案顯然沒有什麼問題。但是如果是將乙個10g大小的日誌檔案讀取,即...