1. 程式人生 > >Python memory error的問題

Python memory error的問題

消失 解法 對象的引用 第三方 選中 字符 調整 trac 繼續

前段時間在讀取一個文件的過程中,竟然出現了Memory Error!簡直讓我懷疑自己買了個假電腦,畢竟是8G內存i7處理器,一度懷疑自己裝了假的內存條。。。。下面說一下幾個解題步驟。。。。一般就是用下面這些方法了,按順序試試。

導致Memory Error異常的常見原因有以下幾種:

  1. 內存中加載的數據量過於龐大,如一次從數據庫取出過多數據;
  2. 集合類中有對對象的引用,使用完後未清空,不能回收;
  3. 代碼中存在死循環或循環產生過多重復的對象實體;
  4. 使用的第三方軟件中的BUG;
  5. 啟動參數內存值設定的過小;

一、逐行讀取

如果你用pd.read_csv來讀文件,會一次性把數據都讀到內存裏來,導致內存爆掉,那麽一個想法就是一行一行地讀它,代碼如下:

data = []
with open(path, ‘r‘,encoding=‘gbk‘,errors=‘ignore‘) as f:
    for line in f:
        data.append(line.split(‘,‘))
        
data = pd.DataFrame(data[0:100])

這就是先用with open把csv的每一行讀成一個字符串,然後因為csv都是靠逗號分隔符來分割每列的數據的,那麽通過逗號分割就可以把這些列都分離開了,然後把每一行的list都放到一個list中,形成二維數組,再轉換成DataFrame。

這個方法有一些問題,首先讀進來之後索引和列名都需要重新調整,其次很多數字的類型都發生了變化,變成了字符串,最後是最後一列會把換行符包含進去,需要用replace替換掉。

不知道為什麽,用了這個操作之後,還是出現了Memory error的問題。基於這些缺點以及遺留問題,考慮第二種解決方案。

二、巧用pandas中read_csv的塊讀取功能

pandas設計時應該是早就考慮到了這些可能存在的問題,所以在read功能中設計了塊讀取的功能,也就是不會一次性把所有的數據都放到內存中來,而是分塊讀到內存中,最後再將塊合並到一起,形成一個完整的DataFrame。

f = open(path)

data = pd.read_csv(path, sep=,,engine = python,iterator=True)
loop = True
chunkSize 
= 1000 chunks = [] index=0 while loop: try: print(index) chunk = data.get_chunk(chunkSize) chunks.append(chunk) index+=1 except StopIteration: loop = False print("Iteration is stopped.") print(開始合並) data = pd.concat(chunks, ignore_index= True)

以上代碼規定用叠代器分塊讀取,並規定了每一塊的大小,即chunkSize,這是指定每個塊包含的行數。

這個方法能夠保持數據的類型,也不需要自己費心思去調整列名和index,比較方便。但不幸的是,我的還是出現了這個問題,如果你的用了這種方法還是出現memory error,你可以繼續往下看。

三、擴充虛擬內存

我在運行代碼的過程中發現,出現memory error錯誤的時候,其實我的內存只用到了40+%,所以其實不太可能會出現這個錯誤啊,所以我查了下,發現有說是內存被限制了,考慮關掉一些可能限制內存的軟件啦,擴大虛擬內存啦,這些的。

擴大虛擬內存的方法(我的系統是win8,不過應該都大同小異):
1、打開 控制面板;
2、找到 系統 這一項;
3、找到 高級系統設置 這一項;
4、點擊 性能 模塊的 設置 按鈕;
5、選擇 高級面板,在 虛擬內存 模塊點擊更改;
6、記得 不要 選中“自動管理所有驅動器的分頁文件大小”,然後選擇一個驅動器,也就是一個盤,選中自定義大小,手動輸入初始大小和最大值,當然,最好不要太大,更改之後能在查看盤的使用情況,不要丟掉太多空間。
7、都設置好之後,記得點擊 “設置”, 然後再確定,否則無效,最後 重啟電腦 就可以了。

悲劇的是我在設置完這一步之後還是出現了內存錯誤,到這一步就沒有問題了的朋友就可以不用看下面一種解法了,如果還是有問題,可以接下來看。

四、更新Pandas和Numpy庫為64位

如果你的Python用的是32位的,那麽你的pandas和Numpy也只能是32位的,那麽當你的內存使用超過2G時,就會自動終止內存。發現這個錯誤也是因為我察覺到報內存溢出的錯誤的時候,我的內存明明顯示只用了40+%,然後錯誤提示是在pandas的core中,所以查了一下,發現原來還有這麽個大坑。

解決方法就是:先檢查一下你的python是多少位的,在shell中輸入python,查看位數,如果是32位,那麽就重裝Python,裝一個64位的,但同時你的庫也需要重新裝了。不過我執行完這一步之後,問題就完美解決了!

五、如果還有內存溢出的錯

以上四種方法,按順序逐一使用,到哪一步錯誤消失了就可以停止啦。當然了,還會有其他的情況,比如查看一下內存的進程,看是否還活著,內存進程掛掉的話,也會報內存錯誤,不常見。如果你的內存顯示使用達到了99%+,那麽就是內存真的不夠用,不是別的問題,如果不是數據量特別大,那就是寫代碼的時候的習慣問題,雖然Python有垃圾回收機制,但是有時候可能來不及回收,尤其是在循環叠代這些過程中,往往會循環完畢了才來得及收拾垃圾,所以記得及時把不要的變量del掉,或者用gc這個垃圾回收庫,這樣內存自然就一直清清爽爽啦~

Python memory error的問題