2013-07-12 4 views
8

pracuję z przecinkami/pliki danych rozdzielone tabulatorami często, że może wyglądać tak:Czy mogę przesyłać strumieniowo listę pickletów Pythona, krotek lub inny typ danych iteracyjnych?

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

mogę czytać i pre-proces ten w Pythonie na listę list tak:

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

Czasami lubię zapisywać tę listę list jako pikle, ponieważ zachowuje ona różne typy moich wpisów. Jeśli jednak plik jest duży, dobrze byłoby przeczytać tę listę z powrotem w strumieniu strumieniowym.

W Pythonie, aby załadować plik tekstowy w postaci strumienia, używam follwoing wydrukować każdym wierszu:

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

mogę zrobić coś podobnego do listy Pythona, a mianowicie:

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 

Czy istnieje funkcja piklowania, np. "Load_streaming"?

+1

Co masz na myśli przez "streamingu"? co chcesz "wejść"? zauważ także, że twój kod, jak napisałeś, prawdopodobnie nie robi tego, co masz zamiar. miałeś na myśli 'dla wejścia w pkl' zamiast' dla wejścia w p'? – shx2

+0

Myślę, że przez "streaming" oznacza iterowanie pliku pikle jako sekwencji pikli, w ten sam sposób, jak można przetworzyć plik tekstowy jako sekwencję linii, tak jak odpowiada odpowiedź mata. – abarnert

Odpowiedz

9

To działałoby.

Co robi jednak jest unpickle jeden obiekt z pliku, a następnie wydrukować resztę zawartości pliku, do stdout

Co można zrobić, to coś takiego:

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

Że unpickle wszystko obiekty z pliku, aż do osiągnięcia EOF.


Jeśli chcesz coś, co działa jak for line in f:, można to owinąć się łatwo:

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

Teraz można po prostu to zrobić:

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

Teraz połącz swoją odpowiedź z dekoratorem [contextlib] (http://docs.python.org/2/library/contextlib.html) i możesz to zrobić z unpickle (nazwa pliku): ' – dawg

+0

@drewk - Masz na myśli na wypadek gdyby iterator nie jest w pełni zużyty lub podczas iteracji powstaje wyjątek ... Tak, tęskniłem za tym. Ale nie sądzę, że "contextlib.contextmanager" byłby tu bardzo użyteczny i znacznie bardziej skomplikowany niż rozwiązanie [pierwotnie sugerowane przez abarnet] (http: // stackoverflow.com/rewizje/17623631/2) jawnego otwierania pliku jako menedżera kontekstu - więc powracam do tego. – mata

+0

@mata Hmm, przykro mi, nie sądzę, żebym był jasny, więc zredagowałem moje pytanie. Zwykle mam listę list jako mój wytrawiony obiekt, a nie cały zbiór wytrawionych obiektów. Aby wyświetlić listę list w big_pickled_list, Twoja sugestia nie działa. Czy jednak powinienem inaczej przechowywać przedmioty w moim ogórku? – williampli

0

Aby śledzić na komentarz Zrobiłem na przyjętym rozwiązaniu, polecam pętlę bardziej podobną do tej:

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

W ten sposób będziesz otrzymywać wyjątek EOFError, jeśli w pliku znajduje się uszkodzony obiekt.

Dla kompletności:

def unpickle_iter(file): 
    while file.peek(1): 
     yield cPickle.load(file) 
Powiązane problemy