2010-06-09 11 views
4

Pour une raison quelconque, je ne peux pas obtenir cPickle.load pour travailler sur l'objet de type fichier retourné par ZipFile.open(). Si j'appelle read() sur l'objet de type fichier retourné par ZipFile.open(), je peux cependant utiliser cPickle.loads.charger un fichier pickle à partir d'un fichier zip

Exemple ....

import zipfile 
import cPickle 

# the data we want to store 
some_data = {1: 'one', 2: 'two', 3: 'three'} 

# 
# create a zipped pickle file 
# 
zf = zipfile.ZipFile('zipped_pickle.zip', 'w', zipfile.ZIP_DEFLATED) 
zf.writestr('data.pkl', cPickle.dumps(some_data)) 
zf.close() 

# 
# cPickle.loads works 
# 
zf = zipfile.ZipFile('zipped_pickle.zip', 'r') 
sd1 = cPickle.loads(zf.open('data.pkl').read()) 
zf.close() 

# 
# cPickle.load doesn't work 
# 
zf = zipfile.ZipFile('zipped_pickle.zip', 'r') 
sd2 = cPickle.load(zf.open('data.pkl')) 
zf.close() 

Note: Je ne veux pas zip juste le fichier cornichon, mais de nombreux fichiers d'autres types. C'est juste un exemple.

+0

avez-vous essayé 'import picklefork'? : P – FrustratedWithFormsDesigner

+3

Essayez de nous dire ce que «ne fonctionne pas» signifie dans ce cas; nous n'avons pas de boules de cristal. –

+0

@John, à quel point est-il difficile de copier et de dépasser le code qu'il a donné? Il obtient un 'EOFError' dans le dernier extrait. –

Répondre

7

Cela est dû à une imperfection dans l'objet pseudofichier implémenté par le module zipfile (pour la méthode .open de la classe ZipFile introduite dans Python 2.6). Tenir compte:

>>> f = zf.open('data.pkl') 
>>> f.read(1) 
'(' 
>>> f.readline() 
'dp1\n' 
>>> f.read(1) 
'' 
>>> 

la séquence de .read(1)-.readline() est ce que .loads interne ne (sur un cornichon protocole 0, la valeur par défaut en Python 2, qui est ce que vous utilisez ici). Malheureusement, l'imperfection de zipfile signifie que cette séquence particulière ne fonctionne pas, produisant une fausse "fin de fichier" (.read retournant une chaîne vide) juste après la première paire read/readline.

Je ne suis pas sûr si ce bogue dans la bibliothèque standard de Python est corrigé dans Python 2.7 - Je vais vérifier.

Modifier: juste vérifié - le bogue est corrigé dans Python 2.7 rc1 (le candidat à la version qui est actuellement la dernière version 2.7). Je ne sais pas encore si c'est corrigé dans la dernière version de correction de bug de 2.6.

Modifier à nouveau: le bug est toujours là en Python 2.6.5, la dernière version bug-fix de Python 2.6 - donc si vous ne pouvez pas passer à 2,7 et ont besoin de mieux se comporter-objets pseudofichier de ZipFile.open, un backport du 2.7 fix semble la seule solution viable.

Notez qu'il n'est pas certain que do besoin d'un meilleur pseudofile; si vous contrôlez les appels de vidage et peut utiliser la dernière et le plus grand protocole, tout ira bien:

>>> zf = zipfile.ZipFile('zipped_pickle.zip', 'w', zipfile.ZIP_DEFLATED) 
>>> zf.writestr('data.pkl', cPickle.dumps(some_data, -1)) 
>>> sd2 = cPickle.load(zf.open('data.pkl')) 
>>> 

c'est seulement vieux crufty « protocole 0 » rétrocompatible (la valeur par défaut) qui exige un comportement objet pseudofichier approprié lors du mélange des appels readline et readline dans le load (le protocole 0 est également plus lent et entraîne des pickles plus importants, donc ce n'est pas recommandé à moins d'être compatible avec les anciennes versions de Python ou la nature ascii des pickles contraintes dans votre application).

+0

Je reçois la même fausse EOFError en utilisant les protocoles 1 et 2 sur python 2.6.6. – dvogel

Questions connexes