2013-07-12 3 views
8

Io lavoro con virgola/file di dati separati da tabulazione spesso che potrebbe essere simile a questo:È possibile eseguire lo streaming di un elenco pickle Python, tupla o altro tipo di dati iterabile?

key1,1,2.02,hello,4 
key2,3,4.01,goodbye,6 
... 

potrei leggere e pre-processo questo in Python in una lista di liste, in questo modo:

[ [ key1, 1, 2.02, 'hello', 4 ], [ key2, 3, 4.01, 'goodbye', 6 ] ] 

A volte, mi piace salvare questo elenco di elenchi come un sottaceto, dal momento che conserva i diversi tipi delle mie voci. Se il file in pickled è grande, sarebbe bello leggere questo elenco di liste in streaming.

In Python, per caricare un file di testo come un flusso, io uso il follwoing di stampare ogni linea:

with open('big_text_file.txt') as f: 
    for line in f: 
     print line 

Posso fare qualcosa di simile per una lista Python, vale a dire:

import pickle 
with open('big_pickled_list.pkl') as p: 
    for entry in pickle.load_streaming(p): # note: pickle.load_streaming doesn't exist 
     print entry 

Esiste una funzione di pickle come "load_streaming"?

+1

Che cosa si intende per "streaming"? cosa vuoi che "entrata" sia? anche notare che il tuo codice, come pubblicato, probabilmente non sta facendo quello che intendi. volevi dire "per l'entrata in pkl' invece di" per l'entrata in p'? – shx2

+0

Penso che con "streaming" intenda iterare un file pickle come una sequenza di sottaceti, allo stesso modo in cui è possibile iterare un file di testo come una sequenza di linee, come fa la risposta di mata. – abarnert

risposta

9

Questo funzionerebbe.

Qual è lo fa però è deserializzazione un oggetto dal file, e quindi stampare il resto del contenuto del file per stdout

cosa si potrebbe fare è qualcosa di simile:

import cPickle 
with open('big_pickled_list.pkl') as p: 
    try: 
     while True: 
      print cPickle.load(p) 
    except EOFError: 
     pass 

Questa sarebbe la deserializzazione tutto oggetti dal file fino a raggiungere EOF.


Se si desidera qualcosa che funziona come for line in f:, si può avvolgere questo facilmente:

def unpickle_iter(file): 
    try: 
     while True: 
      yield cPickle.load(file) 
    except EOFError: 
     raise StopIteration 

Ora si può semplicemente fare questo:

with open('big_pickled_list.pkl') as file: 
    for item in unpickle_iter(file): 
     # use item ... 
+0

Ora unisci la tua risposta al decoratore [contextlib] (http://docs.python.org/2/library/contextlib.html) e puoi fare 'con unpickle (nome file):' – dawg

+0

@drewk - Vuoi dire nel caso l'iteratore non è completamente consumato o viene sollevata un'eccezione durante l'iterazione ... Sì, l'ho perso. Ma non penso che un 'contextlib.contextmanager' sarebbe molto utile qui, e molto più complicato della soluzione [originariamente suggerito da abarnet] (http: // StackOverflow.it/revisions/17623631/2) di aprire esplicitamente il file come gestore del contesto, quindi sto tornando a quello. – mata

+0

@mata Hmm, mi dispiace, non penso di essere stato chiaro, quindi ho modificato la mia domanda. Di solito ho un elenco di elenchi come oggetto decapato, non un intero set di oggetti decapati. Per un elenco di elenchi in big_pickled_list, il tuo suggerimento non funziona. Tuttavia, dovrei conservare oggetti nel mio pickle in modo diverso? – williampli

0

dare un seguito a un commento Ho fatto sulla soluzione accettata, mi consiglia un ciclo più simile al seguente:

import cPickle 
with open('big_pickled_list.pkl') as p: 
    while p.peek(1): 
     print cPickle.load(p) 

In questo modo continuerai a ricevere l'eccezione EOFError se nel file è presente un oggetto danneggiato.

Per completezza:

def unpickle_iter(file): 
    while file.peek(1): 
     yield cPickle.load(file) 
Problemi correlati