将列表中的变量引用传递给pickle

时间:2015-09-10 11:39:01

标签: python list file-io pass-by-reference pickle

我有一段代码在数据库中运行搜索,并根据结果生成新的搜索。它通过生成包含新搜索词的列表来完成此操作。由于代码可以运行很长时间,我试图用cPickle支持这个列表(以及其他一些包含其他重要值的列表),以便在发生崩溃时恢复搜索。

列表本身可以包含数百万个条目(每个条目是一些短数字的字符串),因此可以变得非常大。

如果我的代码崩溃,我可以在重新启动时恢复列表并继续我的搜索,就好像什么都没发生一样。但问题是,如果列表太大(或者我的机器上的不同进程使用了​​大量RAM),我最终会收到MemoryError。

我写的代码是为了确保这不会破坏我之前的备份,如下所示:

import os, time
import cPickle as pickle

def pickle_securely(value_pairs, exception_log, current_path):
    os.chdir(current_path)
    try:
        # pickle variables
        for value in value_pairs:
            filename = value[1] 
            var_name = value[0]
            #remove file extension
            filename_body = filename.split('.')[0]
            filename_temp = filename_body + '.temp'
            with open(filename_temp, 'wb') as filename_temp_pkl:
                pickle.dump(var_name, filename_temp_pkl, -1)

        # once all variables have been pickled successfully, replace the old files    
        for value in value_pairs:
            filename = value[1] 
            var_name = value[0]
            #remove file extension
            filename_body = filename.split('.')[0]
            filename_temp = filename_body + '.temp'
        if os.path.isfile(filename) == True:
            os.remove(filename)
        os.rename(filename_temp, filename)
    except Exception as e:
        s = traceback.format_exc()
        serr = "%s" % (s)
        error_message = "Pickling " + str(var_name) + " into " + str(backup_name) + " has failed."
        error_message = "\n" + time.strftime("%d/%m/%Y %H:%M:%S") + "\n" + error_message + serr +"\n" + "\n"
        print error_message
        exception_log.write(error_message)
        raise

我当前写的方式我传递了一个列表,其中包含变量对和要被腌制到该函数的文件的名称(我显然不想硬编码我将拥有多少变量因为这可能会根据我使用此函数的位置而改变,这就是我使用列表作为外部结构的原因。)

看到我的列表(带有搜索结果)但非常大,我宁愿将对这些列表的引用传递给函数,而不是包含所有这些列表的副本的列表,以保持低内存使用率。

到目前为止,我还没有找到一种很好的方法,但是,不可否认,也许我的方法并不是最优雅的。有人可能会指出我正确的方向吗? (或者建议我如何重新编写函数以便我不需要它?)

编辑:经过大量的谷歌搜索后,我发现这篇文章Python: Get a pointer to a list element说明Python没有指针。我能够找到的所有示例似乎都关注使用某些对象的可变性在某些子例程中编辑它们。然而,我并不关心这一点,只是想保持低RAM使用率。还有其他方法吗?

1 个答案:

答案 0 :(得分:0)

在尝试了@luoluo在IPython的评论中提到的内容之后,确实将多个列表包装在另一个列表中并不会创建一个新变量,但看起来只是一个引用,正如a = range(10**7)b = range(10**7) c = [a,b]都会导致内存使用量增加,随后调用import java.util.*; class selctionsort { public static void calc() { int i , j; int temp; int n ; Scanner sc=new Scanner(System.in); System.out.println("Enter how many Numbers to be sorted"); n=sc.nextInt(); int a[]=new int [n]; for(i=0;i<n;i++) { System.out.println("Enter The Numbers"); a[i]=sc.nextInt(); } for(i=0;i<n;i++) { for (j=i;j<n;j++) { if(a[i]>a[j]) { temp=a[i]; a[i]=a[j]; a[j]=temp; } } } for(i=0;i<n;i++) { System.out.println("Sorted array is " +a[i]); } } } 会导致内存使用量不再增加。

因此,为了回答这个问题,将列表包装在一个列表中以将它们传递给函数只传递对列表的引用,而不是实际列表的副本。