2016-04-14 60 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