如何在python中保存和恢复多个变量?


104

我需要将大约十二个对象保存到文件中,然后稍后将其还原。我尝试过使用带咸菜和搁置的for循环,但效果不佳。

编辑。
我试图保存的所有对象都在同一个类中(我之前应该提到过),但我没有意识到我可以像这样保存整个类:

import pickle
def saveLoad(opt):
    global calc
    if opt == "save":
        f = file(filename, 'wb')
        pickle.dump(calc, f, 2)
        f.close
        print 'data saved'
    elif opt == "load":
        f = file(filename, 'rb')
        calc = pickle.load(f)
    else:
        print 'Invalid saveLoad option'

1
您说您已经尝试过for循环。请发布该代码,以及为什么“它无法正常工作”(即发生了什么以及您想发生什么)。
布莱尔

如果您使用的是Windows,请确保以二进制方式打开文件
约翰·拉ROOY

@gnibbler:只有非默认协议(docs.python.org/library/pickle.html#usage)才需要二进制模式。
Eric O Lebigot

Answers:


170

如果需要保存多个对象,则可以简单地将它们放在单个列表或元组中,例如:

import pickle

# obj0, obj1, obj2 are created here...

# Saving the objects:
with open('objs.pkl', 'w') as f:  # Python 3: open(..., 'wb')
    pickle.dump([obj0, obj1, obj2], f)

# Getting back the objects:
with open('objs.pkl') as f:  # Python 3: open(..., 'rb')
    obj0, obj1, obj2 = pickle.load(f)

如果您有大量数据,可以通过传递protocol=-1dump(); 来减小文件大小。pickle然后将使用最佳的可用协议,而不是默认的历史记录(以及向后兼容的协议)。在这种情况下,必须以二进制模式打开文件(分别为wbrb)。

二进制模式也应该与Python 3一起使用,因为它的默认协议会生成二进制(即非文本)数据(写入模式'wb'和读取模式'rb')。


12
在Python 3.5中,我不得不以“字节”模式打开文件,例如with open('objs.pickle', 'wb') as f:(请注意wb)。
kbrose '16

嗨@Eric,with open('objs.pkl') as f:比较简单需要什么obj1, obj2 = pickle.load(open("objs.pkl","rb"))?两者之间有什么区别吗?
balandongiv

使用第二种形式,您不会关闭文件。这不是一个好习惯,因为您可以并行打开的文件数量通常受操作系统的限制(请尝试执行一个打开文件而不关闭它们的循环!)。就是说,实际上,当您不打开许多文件时,不关闭文件通常是可行的。
Eric O Lebigot

49

有一个名为的内置库pickle。使用,pickle您可以将对象转储到文件中并在以后加载它们。

import pickle

f = open('store.pckl', 'wb')
pickle.dump(obj, f)
f.close()

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()

1
我在Python 3.4中使用:f = open('store.pckl', 'wb')打开要写入的文件。请参阅stackoverflow.com/questions/13906623/… 并使用`f = open('store.pckl','rb')打开要读取的文件。请参阅stackoverflow.com/questions/7031699/…
user3731622

这是针对3.4+吗?我几乎否决了这个答案,因为当您不使用'b'时,它会产生错误。
Wilmer E. Henao

12

您应该查看一下货架泡菜模块。如果您需要存储大量数据,最好使用数据库


我想保存一个登录到云服务器的对象,以便处理如果我多次登录后该服务器拒绝我的请求。使用pickle模块将对象转储到文件中是否可能存在任何安全问题?,例如,如果有人获得了我的转储对象,那么他们可以不用密码登录我的云存储。
阿尔珀


4

您可以使用klepto,它为内存,磁盘或数据库提供持久缓存。

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db['1'] = 1
>>> db['max'] = max
>>> squared = lambda x: x**2
>>> db['squared'] = squared
>>> def add(x,y):
...   return x+y
... 
>>> db['add'] = add
>>> class Foo(object):
...   y = 1
...   def bar(self, x):
...     return self.y + x
... 
>>> db['Foo'] = Foo
>>> f = Foo()
>>> db['f'] = f  
>>> db.dump()
>>> 

然后,在解释器重新启动后...

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db
file_archive('foo.txt', {}, cached=True)
>>> db.load()
>>> db
file_archive('foo.txt', {'1': 1, 'add': <function add at 0x10610a0c8>, 'f': <__main__.Foo object at 0x10510ced0>, 'max': <built-in function max>, 'Foo': <class '__main__.Foo'>, 'squared': <function <lambda> at 0x10610a1b8>}, cached=True)
>>> db['add'](2,3)
5
>>> db['squared'](3)
9
>>> db['f'].bar(4)
5
>>> 

在此处获取代码:https : //github.com/uqfoundation


7
OP没有要求内置。
Mike McKerns,2015年

4

以下方法似乎很简单,可以与不同大小的变量一起使用:

import hickle as hkl
# write variables to filename [a,b,c can be of any size]
hkl.dump([a,b,c], filename)

# load variables from filename
a,b,c = hkl.load(filename)

hickle与相比,package更健壮(更不容易出错),甚至更简单(更少代码)pickle
user2340939
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.