3

我想一次性将我在特定函数中创建的所有变量保存到磁盘,以便以后加载它们。某种类型的东西:

>>> def test():
      a=1
      b=2
      save.to.file(filename='file', all.variables)

>>> load.file('file')
>>> a
>>> 1

有没有办法在python中做到这一点?我知道 cPickle 可以做到这一点,但据我所知,必须为每个变量键入 cPickle.dump(),而我的脚本有几十个。此外,cPickle 似乎只存储变量的值而不是名称,因此必须记住数据最初保存的顺序。

4

4 回答 4

2

假设您要保存的所有变量都是当前函数的本地变量,您可以通过函数获取它们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)}
于 2013-08-05T22:48:40.273 回答
1

If you are not satisfied with the API of pickle, consider shelve which does the pickling for you with a nicer dict-like front end.

ex.

>>> 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)]
于 2013-08-05T21:57:24.183 回答
1

您可以使用 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

于 2013-08-05T22:00:05.493 回答
0

您可以通过使它们成为对象的属性或字典中的元素来腌制多个变量。在任何一种情况下,它都会保存名称。它不像在 MATLAB 中保存那么方便,但总比没有好。

于 2013-08-05T21:52:19.017 回答