¿Guardando y cargando múltiples objetos en un archivo pickle?

Tengo una clase que sirve a los jugadores en un juego, los crea y otras cosas.

Necesito guardar estos objetos de jugador en un archivo para usarlos más tarde. He probado el módulo pickle pero no sé cómo guardar varios objetos y volver a cargarlos. ¿Hay alguna forma de hacerlo o debo usar otras clases como listas y guardar y cargar mis objetos en una lista?

¿Hay alguna manera mejor?

Usar una lista, una tupla o un dictado es, con mucho, la forma más común de hacer esto:

 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) 

Que imprime

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

Sin embargo, un archivo de encurtido puede contener cualquier número de encurtidos. Aquí está el código que produce el mismo resultado. Pero tenga en cuenta que es más difícil escribir y entender:

 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 

Si haces esto, eres responsable de saber cuántas pepinillos hay en el archivo que escribes. El código anterior lo hace seleccionando primero el número de objetos de la lista.

Dos adiciones a la respuesta aceptada de Tim Peters .

Primero , no necesita almacenar la cantidad de elementos que decantó por separado si deja de cargar cuando llega al final del archivo:

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

Esto supone que el archivo solo contiene pepinillos; Si hay algo más allí, el generador intentará tratar cualquier cosa que esté allí como pepinillos, lo que podría ser peligroso.

En segundo lugar , de esta manera, no se obtiene una lista, sino un generador . Esto cargará solo un elemento en la memoria a la vez, lo que es útil si los datos volcados son muy grandes, una posible razón por la que quizás haya querido recoger varios artículos por separado en primer lugar. Todavía puede iterar sobre los items con un bucle for como si fuera una lista.

Prueba esto:

 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() 

Daré una demostración orientada a objetos utilizando pickle para almacenar y restaurar uno o varios object :

 class Worker(object): def __init__(self, name, addr): self.name = name self.addr = addr def __str__(self): string = u'[ 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_restre = pickle.load(f) print 'item: %s' %w1_restre # 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 

salida:

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

Es fácil si usa klepto , lo que le brinda la capacidad de almacenar objetos de forma transparente en archivos o bases de datos. Utiliza una API dict, y le permite dump y / o load entradas específicas de un archivo (en el caso a continuación, los objetos serializados almacenan una entrada por archivo en un directorio llamado 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 >>>