2016-04-14 79 views
2

我正在處理一個大數據項目,而且當我運行我的腳本時,經常遇到MemoryError。它包含一個由我的腳本讀取的文件列表上的循環,在3或4個文件後,出現此錯誤。MemoryError後刪除變量

我覺得寫這樣的事情:

with open("E:\New_Fields\liste_essai.txt", "r") as f : 

    fichier_entier = f.read() 
    files = fichier_entier.split("\n") 

for fichier in files : 

    with open(fichier, 'r') : 

    # CONDITIONS 

    del var1 
    del var2 
    del var3 

要這樣,我可以釋放內存到下一個循環,這是說,下一個文件。

但有其刪除我的循環的所有變量只用一個命令,而不是手動使這一過程的方法? 在我的腳本中,我可能有15個變量,所以從我的角度來看,它並沒有被優化爲逐個刪除每個變量。

編輯:

我的文件的列表是這樣的:

E:\New_Fields\Field101_combined_final_roughcal.fits 
E:\New_Fields\Field117_combined_final_roughcal.fits 
E:\New_Fields\Field150_combined_final_roughcal.fits 
E:\New_Fields\Field36_combined_final_roughcal.fits 
E:\New_Fields\Field41_combined_final_roughcal.fits 
E:\New_Fields\Field169_combined_final_roughcal.fits 
E:\New_Fields\Field47_combined_final_roughcal.fits 
E:\New_Fields\Field43_combined_final_roughcal.fits 
E:\New_Fields\Field39_combined_final_roughcal.fits 
E:\New_Fields\Field45_combined_final_roughcal.fits 
E:\New_Fields\Field6_combined_final_roughcal.fits 
E:\New_Fields\Field49_combined_final_roughcal.fits 
E:\New_Fields\Field51_combined_final_roughcal.fits 

SCRIPT:

# -*- coding: utf-8 -*- 
#!/usr/bin/env python 

from astropy.io import fits 
import numpy as np 

       ################################### 
       # Fichier contenant le champ brut # 
       ################################### 

with open("E:\New_Fields\liste_essai.txt", "r") as f : 

    fichier_entier = f.read() 
    files = fichier_entier.split("\n") 

for fichier in files : 

    with open(fichier, 'r') : 

      outname = fichier.replace('combined_final_roughcal', 'mask') 

     # Ouverture du fichier à l'aide d'astropy 
     field = fits.open(fichier) 
     print "Ouverture du fichier : " + str(fichier)  
     print " " 

     # Lecture des données fits 
     tbdata = field[1].data 
     print "Lecture des données du fits"    

         ############################### 
         # Application du tri sur PROB # 
         ############################### 

     mask = np.bitwise_and(tbdata['PROB'] < 1.1, tbdata['PROB'] > -0.1) 
     new_tbdata = tbdata[mask] 
     print "Création du Masque"  
     print " " 

        ################################################# 
        # Détermination des valeurs extremales du champ # 
        ################################################# 

     # Détermination de RA_max et RA_min 
     RA_max = np.max(new_tbdata['RA']) 
     RA_min = np.min(new_tbdata['RA']) 
     print "RA_max vaut :  " + str(RA_max) 
     print "RA_min vaut :  " + str(RA_min) 

     # Détermination de DEC_max et DEC_min 
     DEC_max = np.max(new_tbdata['DEC']) 
     DEC_min = np.min(new_tbdata['DEC']) 
     print "DEC_max vaut : " + str(DEC_max) 
     print "DEC_min vaut : " + str(DEC_min) 

        ######################################### 
        # Calcul de la valeur centrale du champ # 
        ######################################### 

     # Détermination de RA_moyen et DEC_moyen 
     RA_central = (RA_max + RA_min)/2. 
     DEC_central = (DEC_max + DEC_min)/2. 

     print "RA_central vaut : " + str(RA_central) 
     print "DEC_central vaut : " + str(DEC_central) 

     print " " 
     print " ------------------------------- " 
     print " " 

       ############################## 
       # Détermination de X et de Y # 
       ############################## 


     # Creation du tableau 
     new_col_data_X = array = (new_tbdata['RA'] - RA_central) * np.cos(DEC_central) 
     new_col_data_Y = array = new_tbdata['DEC'] - DEC_central 
     print 'Création du tableau' 


     # Creation des nouvelles colonnes 
     col_X = fits.Column(name='X', format='D', array=new_col_data_X) 
     col_Y = fits.Column(name='Y', format='D', array=new_col_data_Y) 
     print 'Création des nouvelles colonnes X et Y' 


     # Creation de la nouvelle table 
     tbdata_final = fits.BinTableHDU.from_columns(new_tbdata.columns + col_X + col_Y) 

     # Ecriture du fichier de sortie .fits 
     tbdata_final.writeto(outname) 
     print 'Ecriture du nouveau fichier mask : ' + outname 

     del field, tbdata, mask, new_tbdata, new_col_data_X, new_col_data_Y, col_X, col_Y, tbdata_final 


     print " " 
     print " ......................................................................................" 
     print " " 

謝謝;)

+3

不要讀取文件一次,由線讀取線,一旦名都被重新分配或走出去的範圍舊值將被gc'd所以你不需要做任何事情,那麼幾乎可以肯定因爲你的文件很大,並且一下子就把整個文件讀入內存中例如你實際上暫時保留兩個完整副本 –

+0

重新定義文件到'files = []' –

+0

我只需要用[]替換fichier_entier.split(「\ n」)? – Deadpool

回答

2

縱觀astropy docs for opening-a-fits-file

open()函數有幾個可選參數,這些參數將在後面的章節中討論。如上例所示,默認模式是「只讀」。 open函數返回一個名爲HDUList的對象,它是HDU對象的列表形式的集合。

這樣在內存中創建一個巨大的列表,它是最有可能您的問題,有部分working-with-large-files

的open()函數支持memmap=True論點,即允許每個陣列數據HDU可以通過mmap訪問,而不是一次讀入內存。這對於處理不能完全放入物理內存的非常大的數組非常有用。

這應該有助於減少內存消耗,使用mmap唯一的問題是作爲文檔提到,你會在32位系統上限於文件約2-E演出,但你也將受到物理內存的限制在一個32位系統,所以你的4演出文件不適合內存。可能有其他方法來限制你的內存使用量,但嘗試使用mmap並查看它是如何工作的。

+0

謝謝你的回答,我會深入地閱讀你的鏈接並嘗試解決問題;) – Deadpool

+0

我會嘗試添加'fits.open(file,'readonly',memmap = True)'並觀察它是否更好 – Deadpool

1

首先,我會回答您的具體問題(請注意,你的情況,這不是一個真正的解決方案):

finally: 
    del var1, var2, etc 
    gc.collect() 

  • 讓他們走出去的範圍,例如循環分離成一個單獨的函數

你不能「自動」超越這一進程,因爲如果你只需要擺脫一些變量,Python不能知道哪些除非你告訴它到底。
gc.collect()是需要的,因爲作爲運行時,Python不會「刪除」而是「解除綁定」對象。通常情況下,您很樂意等到下一次自動收集,但不是在這種情況下。

或者,some scopes can be edited as dict's,但that's not the primary way to do it,函數作用域不能在CPython中像這樣編輯。


現在,你有真正問題是在糟糕的設計:

  • 如果你定期打MemoryError,這已經意味着你做錯了和/或你的算法不適合你的環境。正如MemoryError hook in Python?所說,內存不足的情況不可能由不屬於內存管理器一部分的代碼可靠地處理,並且在垃圾回收環境中,它應該是處理內存的垃圾回收器,而不是你。

    • 專門爲「做錯了」:即使在您發佈的代碼,我看到了很多的冗餘副本
  • 如果你有這麼多的變量,你創建使用的首先 - 爲什麼刪除它們最後這麼麻煩給你?
    這是一個告訴你的範圍過大,而這部分必須要麼

    • 拆分出來作爲一個單獨的功能,和/或
    • 分割成更小的部分,以清理每個
+0

非常感謝你的回答!我會試着用你的建議來解決我的問題:) – Deadpool