2010-10-19 7 views
7

Je veux faire (et décoder) une seule chaîne composée de plusieurs pickles python.Est-ce que Python Pickle a un caractère/séquence illégal que je peux utiliser comme séparateur?

Existe-t-il un caractère ou une séquence pouvant être utilisé en tant que séparateur dans cette chaîne?

je devrais être en mesure de faire la chaîne comme ceci:

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

je devrais être en mesure de prendre cette chaîne et à reconstruire les objets comme ceci:

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

Que faut-PICKLE_SEPARATOR être?


Pour les curieux, je veux envoyer des objets décapés à redis en utilisant APPEND. (bien que j'utilise peut-être simplement RPUSH)

+0

Puisque les valeurs peuvent être des collections redis de chaînes, pourquoi ne pas stocker que chacun séparément? – martineau

Répondre

-1

Une solution serait de préfixer votre chaîne de cornichons avec des données sur le nombre de caractères que contient chaque élément constitutif.

2

Je n'utilise pas beaucoup Python, mais y a-t-il une raison pour laquelle vous ne pouvez pas choisir un tableau à la place? Ainsi, le décapage devient

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

et reconstruction devient

objs = pickle.loads(s) 

Edit 1: En outre, selon this answer, la sortie est décapée auto-terminaison; Ainsi, vous pouvez décaper avec

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

et restaurer avec

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

Je ne suis pas sûr qu'il ya un avantage à cela, cependant. (Bien que je ne voyais pas, il peut y avoir une meilleure façon que cette boucle/combo d'exception méchante, comme je l'ai dit, je ne l'utilise Python beaucoup.)

+0

Cela ne fonctionnera pas pour les flux, malheureusement.J'ai besoin de lire la chaîne séparément car je ne peux pas utiliser pickle 'load' mais seulement' loads' – VF1

2

EDIT: Considérons d'abord la réponse de gnibbler, ce qui est évidemment beaucoup plus simple. La seule raison de préférer celle ci-dessous est si vous voulez pouvoir séparer une séquence de cornichons sans les analyser. Un pari assez sûr consiste à utiliser un UUID flambant neuf que vous ne réutilisez jamais ailleurs. Évaluez uuid.uuid4().bytes une fois et stockez le résultat dans votre code en tant que séparateur. .: par exemple

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

ensuite copier-coller la chaîne résultante littérale dans votre code comme séparateur (ou même simplement utiliser celui ci-dessus, si vous voulez). Il est pratiquement garanti que la même séquence ne se produira jamais dans tout ce que vous voulez stocker.

7

Il est bien juste concaténer les conserves au vinaigre ensemble, Python sait où chacun se termine

>>> 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 gotcha potentiel: cela ne fonctionne pas pour les chaînes, seulement les objets de type fichier: try 'pickle.load (s)' trois fois, seul le 'dict' est renvoyé. –

Questions connexes