在MemoryError之后删除变量

时间:2016-04-14 17:29:27

标签: python memory

我正在处理一个包含大数据的项目,并且在运行脚本时经常会遇到MemoryError。它包含一个由我的脚本读取的文件列表上的循环,在3或4个文件之后,会出现此错误。

我想写下这样的东西:

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

脚本:

# -*- 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 " "

谢谢;)

2 个答案:

答案 0 :(得分:2)

查看opening-a-fits-file的星座文档:

  

open()函数有几个可选参数,将在后面的章节中讨论。默认模式,如上例所示,是“只读”。 open函数返回一个名为HDUList的对象,它是一个类似列表的HDU对象集合。

因此,在内存中创建一个巨大的列表,这很可能是您的问题,有一个部分working-with-large-files

  

open()函数支持memmap=True参数,该参数允许使用mmap访问每个HDU的数组数据,而不是一次性读入内存。这对于处理不能完全适合物理内存的非常大的数组特别有用。

这应该有助于减少内存消耗,mmap的唯一问题就像文档提到的那样,你会受限于32位系统到2-e gigs周围的文件,但是你也会被32的物理内存限制位系统,所以你的4 gig文件不适合内存。可能还有其他方法可以限制内存使用量,但请尝试使用mmap并查看其工作原理。

答案 1 :(得分:1)

首先,我将回答您的具体问题(请注意,在您的情况下,这不是一个真正的解决方案):

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

  • 使它们超出范围,例如将循环分成单独的函数

你不能“自动化”这个过程,因为如果你只需要摆脱一些变量,除非你准确地告诉它,否则Python无法知道哪些变量。
需要gc.collect()因为,作为garbage collection的运行时,Python不会“删除”而是“取消绑定”对象。通常情况下,您很乐意等到下一次自动收集,但不是在这种情况下。

或者,some scopes can be edited as dict's,但that's not the primary way to do it和函数范围无论如何都无法在CPython中进行编辑。

现在,你所遇到的真正的问题都在糟糕的设计中:

  • 如果您定期点击MemoryError,这已经意味着您做错了和/或您的算法不适合您的环境。正如MemoryError hook in Python?所说,内存条件无法通过不属于内存管理器的代码和垃圾收集环境中的代码可靠地处理,它是垃圾收集器应该是处理记忆,而不是你。

    • 专门针对“做错了”:即使在你发布的代码中,我也看到了很多冗余的副本
  • 如果你有创建的使用这么多的变量 - 为什么删除它们对你这么麻烦?
    这可以说明你的范围太大了,这个部分必须是

    • 拆分为单独的功能,和/或
    • 拆分成较小的部分,每次
    • 后进行清理