在函数中保存变量 - python
Posted
技术标签:
【中文标题】在函数中保存变量 - python【英文标题】:saving variables within function - python 【发布时间】:2013-08-05 21:47:28 【问题描述】:我想一次性将我在特定函数中创建的所有变量保存到磁盘,以便以后加载它们。类似的东西:
>>> def test():
a=1
b=2
save.to.file(filename='file', all.variables)
>>> load.file('file')
>>> a
>>> 1
有没有办法在 python 中做到这一点?我知道 cPickle 可以做到这一点,但据我所知,必须为每个变量键入 cPickle.dump(),而我的脚本有几十个。此外,cPickle 似乎只存储变量的值而不存储变量的名称,因此必须记住数据最初保存的顺序。
【问题讨论】:
为什么不腌制整个函数呢?您可以使用test.a
或test.b
来检索变量。
@zhangyangyu:没有。函数属性不是局部变量。
为什么会有几十个变量,每个变量都需要保存?在我看来,要么你使用了太多变量,而列表之类的东西更合适,要么你试图保存所有东西,而不是考虑哪些东西需要保存,哪些应该在程序时重置或重建重新启动。
【参考方案1】:
假设您要保存的所有变量都是当前函数的本地变量,您可以通过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
的事实将无效。
这只是这样做是个坏主意的原因之一。
那么,正确的做法是什么?
最简单的,不是拥有一大堆变量,而是拥有一个带有大量键的字典。然后你可以pickle和unpickle dict,一切都很简单。
或者,或者,使用元组显式腌制和取消腌制您想要的变量:
def test():
a = 1
b = 2
pickle.dump(file, (a, b))
def test2():
a, b = pickle.load(file)
print a
在评论中,你说你想腌制一个或多个变量,跳过任何不能腌制的东西。
为了简单起见,假设您实际上只想腌制一个字典,跳过任何无法腌制的值。 (上面应该说明为什么这个解决方案仍然是完全通用的。)
那么,你怎么知道一个值是否可以腌制?试图预测这是一个棘手的问题。即使你有一个所有可腌制类型的完美列表,这仍然无济于事——一个充满整数的列表可以腌制,但一个充满绑定实例方法的列表不能。
这种事情正是为什么EAFP(“请求宽恕比许可更容易”)在像 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)
【讨论】:
谢谢,这正是我想要的。基本上,我只想将给定会话中的所有变量保存在一个文件中,以备将来参考(以防万一我需要返回查看哪些值分配给了哪些变量)。但是有没有办法告诉 pickle 只保存那些“可腌制”的对象,或者告诉 locals() 不要保存“不可腌制”的对象(我收到一条错误消息 - ValueError - 由于这些) . @user2635863:让我用可能有助于解决您的新问题的内容更新答案。 非常感谢您的清晰解释和演示。【参考方案2】:您可以使用 pickle 将对象存储在文件中:
>>> a = 'a': 1, 'b': 2, 'c': 3
>>> a
'a': 1, 'c': 3, 'b': 2
>>>
>>> import pickle
>>> pickle.dump(a, open('a.dump', 'wb'))
>>>
>>> a = None
>>> a
>>>
>>> a = pickle.load(open('a.dump', 'rb'))
>>> a
'a': 1, 'c': 3, 'b': 2
>>>
更多信息请访问:http://docs.python.org/2/library/pickle.html
【讨论】:
【参考方案3】:如果您对pickle
的API 不满意,请考虑shelve,它使用更好的dict
-like 前端为您完成酸洗。
例如
>>> import shelve
>>> f = shelve.open('demo')
>>> f
<shelve.DbfilenameShelf object at 0x000000000299B9E8>
>>> list(f.keys())
['test', 'example']
>>> del f['test']
>>> del f['example']
>>> list(f.keys())
[]
>>> f['a'] = 1
>>> list(f.keys())
['a']
>>> list(f.items())
[('a', 1)]
【讨论】:
【参考方案4】:您可以通过使它们成为对象的属性或字典中的元素来腌制多个变量。在任何一种情况下,它都会保存名称。虽然不如在 MATLAB 中保存方便,但总比没有好。
【讨论】:
以上是关于在函数中保存变量 - python的主要内容,如果未能解决你的问题,请参考以下文章