私はゲームでプレイヤーにサービスを提供し、彼らと他のものを作成するクラスを持っています。
後で使用するには、これらのプレーヤーオブジェクトをファイルに保存する必要があります。 pickleモジュールを試しましたが、複数のオブジェクトを保存して再度ロードする方法がわかりませんか?それを行う方法はありますか、リストなどの他のクラスを使用して、オブジェクトをリストに保存およびロードする必要がありますか?
もっと良い方法はありますか?
これを行う最も一般的な方法は、リスト、タプル、または辞書を使用することです。
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']
ただし、ピクルファイルcanには任意の数のピクルが含まれます。同じ出力を生成するコードを次に示します。ただし、次のように記述して理解するのは難しいことに注意してください。
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
これを行う場合、書き出すファイルにいくつの漬物があるかを知る責任があります。上記のコードは、リストオブジェクトの数を最初にピクルすることでそれを行います。
Tim Petersの受け入れられた答え への2つの追加。
最初に、ファイルの最後に達したときにロードを停止した場合、個別にピクルしたアイテムの数を保存する必要はありません:
def loadall(filename):
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
items = loadall(myfilename)
これは、ファイルにピクルスのみが含まれていることを前提としています。そこに何か他のものがある場合、ジェネレーターはそこにあるものもピクルスとして扱いますが、これは危険です。
Second、この方法では、リストを取得するのではなく、 generator を取得します。これにより、一度に1つのアイテムのみがメモリにロードされます。これは、ダンプされたデータが非常に大きい場合に便利です。 items
ループを使用して、あたかもリストであるかのようにfor
を反復処理できます。
これを試して:
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()
pickle
を使用してオブジェクト指向のデモを行い、1つまたは複数の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]
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
>>>
繰り返しダンプする場合は、同様に繰り返し読む必要があります。
ループを実行できます( 受け入れられた答え が示すように)ファイルの終わりに到達するまで(その時点で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/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}]