2010-10-19 10 views
7

Voglio fare (e decodificare) una singola stringa composta da diversi sottaceti di pitone.Python Pickle ha un carattere/sequenza illegali che posso usare come separatore?

C'è un carattere o una sequenza che è sicuro usare come separatore in questa stringa?

dovrei essere in grado di fare la stringa in questo modo:

s = pickle.dumps(o1) + PICKLE_SEPARATOR + pickle.dumps(o2) + PICKLE_SEPARATOR + pickle.dumps(o3) ... 

dovrei essere in grado di prendere questa stringa e ricostruire gli oggetti in questo modo:

[pickle.loads(s) for s in input.split(PICKLE_SEPARATOR)] 

Quale dovrebbe essere PICKLE_SEPARATOR?


Per i curiosi, desidero inviare gli oggetti in picchiata ai redis utilizzando APPEND. (anche se forse userò semplicemente RPUSH)

+0

Poiché i valori Redis possono essere raccolte di stringhe, perché non basta memorizzare ciascuno separatamente? – martineau

risposta

-1

Una soluzione sarebbe quella di anteporre la stringa di sottaceti con i dati sul numero di caratteri di ciascun elemento costitutivo.

2

Non uso molto Python, ma c'è un motivo per cui non si può semplicemente mettere sottosopra una matrice? Così decapaggio diventa

s = pickle.dumps([o1,o2,o3]) 

e la ricostruzione diventa

objs = pickle.loads(s) 

Edit 1: Inoltre, secondo this answer, uscita in salamoia è auto-terminazione; in tal modo, si potrebbe salamoia con

s = ''.join(map(pickle.dumps,[o1,o2,o3])) 

e ripristino con

import StringIO 
sio = StringIO.StringIO(s) 
objs = [] 
try: 
    while True: objs.append(pickle.load(sio)) 
catch EOFError: 
    pass 

Non sono sicuro che ci sia un beneficio per questo, però. (Anche se non ne ho visto uno, potrebbe esserci un modo migliore di quel brutto loop/combo di eccezioni, come ho detto, non uso molto Python.)

+0

Questo non funzionerà per i flussi, sfortunatamente.Ho bisogno di leggere la stringa separatamente poiché non posso usare pickle 'load' ma solo' loads' – VF1

2

MODIFICA: Prima considera la risposta di gnibbler, che è ovviamente molto più semplice. L'unica ragione per preferire quella qui sotto è se si desidera poter dividere una sequenza di sottaceti senza analizzarli.

Una scommessa abbastanza sicura è quella di utilizzare un UUID nuovo di zecca che non si riutilizza mai da nessun'altra parte. Valutare uuid.uuid4().bytes una volta e memorizzare il risultato nel codice come separatore. Es .:

>>> import uuid 
>>> uuid.uuid4().bytes 
'\xae\x9fW\xff\x19cG\x0c\xb1\xe1\x1aV%P\xb7\xa8' 

Quindi copiare e incollare la stringa risultante letterale nel codice come separatore (o anche solo utilizzare quello sopra, se si desidera). È praticamente garantito che la stessa sequenza non si verificherà mai in qualsiasi cosa tu voglia archiviare.

7

Va bene catenate solo i sottaceti insieme, Python sa dove ognuno finisce

>>> import cStringIO as stringio 
>>> import cPickle as pickle 
>>> o1 = {} 
>>> o2 = [] 
>>> o3 =() 
>>> p = pickle.dumps(o1)+pickle.dumps(o2)+pickle.dumps(o3) 
>>> s = stringio.StringIO(p) 
>>> pickle.load(s) 
{} 
>>> pickle.load(s) 
[] 
>>> pickle.load(s) 
() 
+2

Un potenziale trucco: questo non funziona con le stringhe, solo oggetti simili a file: prova 'pickle.load (s)' tre volte, viene restituito solo il 'dict'. –

Problemi correlati