在函数中保存变量 - 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.atest.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的主要内容,如果未能解决你的问题,请参考以下文章

Python基础:变量进阶(理解)函数进阶

Python基础之变量进阶

Python3 变量进阶

python基础_变量进阶

python-12-变量

Python的变量