假设您要保存的所有变量都是当前函数的本地变量,您可以通过函数获取它们locals
。这几乎总是一个非常糟糕的主意,但它是可行的。
例如:
def test():
a=1
b=2
pickle.dump(file, locals())
如果你print locals()
,你会发现它只是一个字典,每个局部变量都有一个键。所以,当你稍后load
泡菜时,你会得到同样的字典。如果你想将它注入你的本地环境,你可以……但你必须非常小心。例如,这个函数:
def test2():
locals().update(pickle.load(file))
print a
... 将被编译为期望a
是全局的,而不是本地的,因此您已更新本地的事实a
将无效。
这只是这样做是个坏主意的原因之一。
那么,正确的做法是什么?
最简单的是,与其拥有一大堆变量,不如拥有一个带有大量键的字典。然后你可以腌制和解开字典,一切都是微不足道的。
或者,或者,使用元组显式腌制和取消腌制您想要的变量:
def test():
a = 1
b = 2
pickle.dump(file, (a, b))
def test2():
a, b = pickle.load(file)
print a
在评论中,你说你想腌制一个或多个变量,跳过任何不能腌制的东西。
为了使事情更简单,假设您实际上只想腌制一个字典,跳过任何无法腌制的值。(上面应该说明为什么这个解决方案仍然是完全通用的。)
那么,你怎么知道一个值是否可以腌制呢?试图预测这是一个棘手的问题。即使你有一个所有可腌制类型的完美列表,这仍然无济于事——一个充满整数的列表可以腌制,但一个充满绑定实例方法的列表不能。
这种事情正是为什么EAFP(“Easier to Ask Forgiveness than Permission”)是 Python 等鸭式语言中的重要原则。* 找出是否可以腌制的方法是腌制它,看看你是否得到一个例外。
这是一个简单的演示:
def is_picklable(value):
try:
pickle.dumps(value)
except TypeError:
return False
else:
return True
def filter_dict_for_pickling(d):
return {key: value for key, value in d.items() if is_picklable((key, value))}
如果将整个存储过程放在包装函数中,则可以使这变得不那么冗长,并且更有效:
def pickle_filtered_dict(d, file):
for key, value in d.items():
pickle.dump((key, value), file)
except TypeError:
pass
def pickles(file):
try:
while True:
yield pickle.load(file)
except EOFError:
pass
def unpickle_filtered_dict(file):
return {key: value for key, value in pickles(file)}