将列表中的变量引用传递给 pickle
Pass variable references in a list to 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
我目前编写它的方式因此我传递了一个列表,其中包含成对的变量和要被 pickle 到的文件的名称到函数(我显然不想硬编码我有多少变量将会有,因为这可能会根据我使用此函数的位置而改变,这就是为什么我使用列表作为外部结构的原因)。
鉴于我的列表(带有搜索结果)非常大,我宁愿将对这些列表的引用传递给函数,而不是包含所有这些列表副本的列表,以保持低内存使用率。
到目前为止,我还没有找到执行此操作的好方法,不过,不可否认,也许我的方法不是最优雅的。有人能指出我正确的方向吗? (或者建议我如何重写函数以便不需要它?)
编辑: 经过大量谷歌搜索后,我发现这篇文章 Python: Get a pointer to a list element 指出 Python 没有指针。尽管我能够找到的所有示例似乎都与使用某些对象的可变性在某些子例程中编辑它们有关。然而,我并不关心这一点,只是想保持较低的 RAM 使用率。还有其他方法吗?
尝试过@luoluo 在他在 IPython 的评论中提到的内容,确实将多个列表包装在另一个列表中并不会创建一个新变量,而似乎只是一个引用,正如 while a = range(10**7)
和 b = range(10**7)
都会导致内存使用量增加,随后调用 c = [a,b]
不会导致内存使用量进一步增加。
因此,为了回答这个问题,将列表包装在列表中以将它们传递给函数只传递对列表的引用而不是实际列表的副本。
我有一段代码 运行 在数据库中进行搜索,并根据结果生成新的搜索。它通过生成包含新搜索词的列表来实现这一点。由于代码可以 运行 相当长的时间,我正在尝试使用 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
我目前编写它的方式因此我传递了一个列表,其中包含成对的变量和要被 pickle 到的文件的名称到函数(我显然不想硬编码我有多少变量将会有,因为这可能会根据我使用此函数的位置而改变,这就是为什么我使用列表作为外部结构的原因)。
鉴于我的列表(带有搜索结果)非常大,我宁愿将对这些列表的引用传递给函数,而不是包含所有这些列表副本的列表,以保持低内存使用率。
到目前为止,我还没有找到执行此操作的好方法,不过,不可否认,也许我的方法不是最优雅的。有人能指出我正确的方向吗? (或者建议我如何重写函数以便不需要它?)
编辑: 经过大量谷歌搜索后,我发现这篇文章 Python: Get a pointer to a list element 指出 Python 没有指针。尽管我能够找到的所有示例似乎都与使用某些对象的可变性在某些子例程中编辑它们有关。然而,我并不关心这一点,只是想保持较低的 RAM 使用率。还有其他方法吗?
尝试过@luoluo 在他在 IPython 的评论中提到的内容,确实将多个列表包装在另一个列表中并不会创建一个新变量,而似乎只是一个引用,正如 while a = range(10**7)
和 b = range(10**7)
都会导致内存使用量增加,随后调用 c = [a,b]
不会导致内存使用量进一步增加。
因此,为了回答这个问题,将列表包装在列表中以将它们传递给函数只传递对列表的引用而不是实际列表的副本。