在pickle文件中保存和加载多个对象?

问题描述 投票:0回答:9

我有一个类,为游戏中的玩家提供服务,创建他们和其他东西。

我需要将这些播放器对象保存在文件中以便稍后使用。我尝试过 pickle 模块,但我不知道如何保存多个对象并再次加载它们?有没有办法做到这一点,或者我应该使用其他类(例如列表)并在列表中保存和加载我的对象?

有更好的方法吗?

python class object python-3.x pickle
9个回答
157
投票

Tim Peters 接受的答案进行了两项补充。

首先,如果您在到达文件末尾时停止加载,则无需单独存储您腌制的项目数量:

def loadall(filename):
    with open(filename, "rb") as f:
        while True:
            try:
                yield pickle.load(f)
            except EOFError:
                break

items = loadall(myfilename)

这假设文件仅包含泡菜;如果里面还有其他东西,生成器也会尝试将里面的其他东西也视为泡菜,这可能很危险。

第二,这样,你不会得到一个列表,而是一个生成器。 这一次只会将一项加载到内存中,这很有用 如果转储的数据非常大——可能的原因之一是 首先想分别腌制多个项目。 您仍然可以使用

items
循环迭代
for
,就好像它是 一个清单。


109
投票

使用列表、元组或字典是迄今为止最常见的方法:

import pickle
PIK = "pickle.dat"

data = ["A", "b", "C", "d"]
with open(PIK, "wb") as f:
    pickle.dump(data, f)
with open(PIK, "rb") as f:
    print pickle.load(f)

打印:

['A', 'b', 'C', 'd']

但是,pickle 文件可以 包含任意数量的pickle。这是产生相同输出的代码。但请注意,它更难编写和理解:

with open(PIK, "wb") as f:
    pickle.dump(len(data), f)
    for value in data:
        pickle.dump(value, f)
data2 = []
with open(PIK, "rb") as f:
    for _ in range(pickle.load(f)):
        data2.append(pickle.load(f))
print data2

如果你这样做,你就有责任知道你写出的文件中有多少个泡菜。上面的代码通过首先对列表对象的数量进行腌制来实现这一点。


29
投票

试试这个:

import pickle

file = open('test.pkl','wb')
obj_1 = ['test_1', {'ability', 'mobility'}]
obj_2 = ['test_2', {'ability', 'mobility'}]
obj_3 = ['test_3', {'ability', 'mobility'}]

pickle.dump(obj_1, file)
pickle.dump(obj_2, file)
pickle.dump(obj_3, file)

file.close()

file = open('test.pkl', 'rb')
obj_1 = pickle.load(file)
obj_2 = pickle.load(file)
obj_3 = pickle.load(file)
print(obj_1)
print(obj_2)
print(obj_3)
file.close()

13
投票

如果您迭代地转储它,您也必须迭代地读取它。

您可以运行一个循环(如接受的答案所示)继续取消排序行,直到到达文件末尾(此时会出现

EOFError
)。

data = []
with open("data.pickle", "rb") as f:
    while True:
        try:
            data.append(pickle.load(f))
        except EOFError:
            break

最小可验证示例

import pickle

# Dumping step
data = [{'a': 1}, {'b': 2}]
with open('test.pkl', 'wb') as f:
    for d in data:
        pickle.dump(d, f)

# Loading step
data2 = []
with open('test.pkl', 'rb') as f:
    while True:
        try:
            data2.append(pickle.load(f))
        except EOFError:
            break

data2
# [{'a': 1}, {'b': 2}]

data == data2
# True

当然,这是假设您的对象必须单独进行pickle。您还可以将数据存储为单个对象列表,然后使用单个pickle/unpickle调用(不需要循环)。

data = [{'a':1}, {'b':2}]  # list of dicts as an example
with open('test.pkl', 'wb') as f:
    pickle.dump(data, f)

with open('test.pkl', 'rb') as f:
    data2 = pickle.load(f)

data2
# [{'a': 1}, {'b': 2}]

8
投票

我将提供一个面向对象的演示,使用

pickle
来存储和恢复一个或多个
object
:

class Worker(object):

    def __init__(self, name, addr):
        self.name = name
        self.addr = addr

    def __str__(self):
        string = u'[<Worker> name:%s addr:%s]' %(self.name, self.addr)
        return string

# output one item
with open('testfile.bin', 'wb') as f:
    w1 = Worker('tom1', 'China')
    pickle.dump(w1, f)

# input one item
with open('testfile.bin', 'rb') as f:
    w1_restore = pickle.load(f)
print 'item: %s' %w1_restore

# output multi items
with open('testfile.bin', 'wb') as f:
    w1 = Worker('tom2', 'China')
    w2 = Worker('tom3', 'China')
    pickle.dump([w1, w2], f)

# input multi items
with open('testfile.bin', 'rb') as f:
    w_list = pickle.load(f)

for w in w_list:
    print 'item-list: %s' %w

输出:

item: [<Worker> name:tom1 addr:China]
item-list: [<Worker> name:tom2 addr:China]
item-list: [<Worker> name:tom3 addr:China]

0
投票

如果您使用

klepto
,这很容易,它使您能够透明地在文件或数据库中存储对象。它使用 dict API,并允许您从存档中
dump
和/或
load
特定条目(在下面的情况下,序列化对象在名为
scores
的目录中为每个文件存储一个条目)。

>>> import klepto
>>> scores = klepto.archives.dir_archive('scores', serialized=True)
>>> scores['Guido'] = 69 
>>> scores['Fernando'] = 42
>>> scores['Polly'] = 101
>>> scores.dump()
>>> # access the archive, and load only one 
>>> results = klepto.archives.dir_archive('scores', serialized=True)
>>> results.load('Polly')
>>> results
dir_archive('scores', {'Polly': 101}, cached=True)
>>> results['Polly']
101
>>> # load all the scores
>>> results.load()
>>> results['Guido']
69
>>>

0
投票

以下是如何使用 pickle 转储两个(或更多字典)并将其提取回来:

import pickle

dict_1 = {1: 'one', 2: 'two'}
dict_2 = {1: {1: 'one'}, 2: {2: 'two'}}

F = open('data_file1.pkl', 'wb')
pickle.dump(dict_1, F)
pickle.dump(dict_2, F)
F.close()

============================================

import pickle

dict_1 = {1: 'one', 2: 'two'}
dict_2 = {1: {1: 'one'}, 2: {2: 'two'}}

F = open('data_file1.pkl', 'rb')
G = pickle.load(F)
print(G)
H = pickle.load(F)
print(H)
F.close()

0
投票

假设我们在 Employee 类的文件中保存了对象。下面是从文件中一一读取所有对象的代码:

 e = Employee()    

with open(filename, 'rb') as a:
    while True:
        try:
            e = pickle.load(a)
            e.ShowRecord()
        except EOFError:
            break    

0
投票

字典可以方便地使用

pickle
保存任何类型的对象,因为您可以使用键检索它们。

import pickle

def save_to_pickle(filepath, **kwargs):
    objects_dict = kwargs
    with open(filepath, 'wb') as file:
        pickle.dump(objects_dict, file)


a = [1, 2, 3]
b = {"x": 10, "y": 20}
filepath = 'saved_objects.pkl'
save_to_pickle(filepath, array_a=a, dictionary_b=b)

with open(filepath, "rb") as file:
    print(pickle.load(file)["array_a"])

© www.soinside.com 2019 - 2024. All rights reserved.