2013-07-12 4 views
8

ich mit Komma/Tab getrennte Datendateien häufig arbeiten, die wie folgt aussehen könnte:Kann ich eine Python-Beizliste, ein Tupel oder einen anderen iterierbaren Datentyp streamen?

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

könnte ich lesen und Vorprozess dies in Python in eine Liste von Listen, wie folgt aus:

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

Manchmal speichere ich gerne diese Liste von Listen als Beize, da sie die verschiedenen Arten meiner Einträge bewahrt. Wenn die gebeizte Datei jedoch groß ist, wäre es großartig, diese Liste von Listen wieder streamingweise zu lesen.

In Python, eine Textdatei als Stream zu laden, benutze ich das follwoing aus jeder Zeile zu drucken:

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

Kann ich etwas tun, ähnlich für eine Python-Liste, das heißt:

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 

Gibt es eine Beizfunktion wie "load_streaming"?

+1

was meinst du mit "Streaming"? was willst du "entry" sein? Beachten Sie auch, dass Ihr Code, wie er geschrieben wurde, wahrscheinlich nicht das tut, was Sie beabsichtigen. meinst du "für den eintrag in pkl" statt "für den eintrag in p"? – shx2

+0

Ich denke, mit "streaming" bedeutet er, eine Pickle-Datei als eine Folge von Pickles zu wiederholen, genauso wie man eine Textdatei als eine Folge von Zeilen iterieren kann, wie Matas Antwort tut. – abarnert

Antwort

9

Das würde funktionieren.

Was das jedoch ist unpickle ein Objekt aus der Datei, und dann den Rest des Inhalts der Datei drucken zu stdout

Was Sie tun, ist etwas könnte wie:

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

Das ist alles würde unpickle Objekte aus der Datei bis zum Erreichen von EOF.


Wenn Sie wollen etwas, das wie for line in f: funktioniert, können Sie diese leicht einpacken:

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

Jetzt können Sie genau dies tun:

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

Kombinieren Sie nun Ihre Antwort mit dem [contextlib] (http://docs.python.org/2/library/contextlib.html) Decorator und Sie können 'mit dempickle (Dateiname) tun:' – dawg

+0

@drewk - Sie meinen im Fall der Iterator ist nicht vollständig verbraucht oder eine Ausnahme wird beim Iterieren ausgelöst ... Ja, das habe ich verpasst. Aber ich denke nicht, dass ein 'contextlib.contextmanager' hier sehr nützlich wäre, und viel komplizierter als die Lösung [ursprünglich von abarnet vorgeschlagen] (http: // stackoverflow.com/revisions/17623631/2), die Datei explizit als Context Manager zu öffnen - damit komme ich zurück. – mata

+0

@mata Hmm, tut mir leid, ich glaube nicht, dass ich klar war, also habe ich meine Frage bearbeitet. Normalerweise habe ich eine Liste von Listen als mein eingelegtes Objekt, nicht eine ganze Reihe eingelegter Objekte. Für eine Liste von Listen in big_pickled_list funktioniert Ihr Vorschlag nicht. Sollte ich jedoch Objekte in meiner Gurke anders speichern? – williampli

0

Um auf einen Kommentar Follow-up Ich machte auf die akzeptierte Lösung, ich empfehle eine Schleife mehr wie folgt:

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

Auf diese Weise erhalten Sie weiterhin die EOFError-Ausnahme, wenn ein beschädigtes Objekt in der Datei vorhanden ist.

Der Vollständigkeit halber:

def unpickle_iter(file): 
    while file.peek(1): 
     yield cPickle.load(file) 
Verwandte Themen