Pickle: Einlesen einer serialisierten Liste

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ChrisSek
User
Beiträge: 10
Registriert: Samstag 8. Mai 2004, 13:06
Wohnort: Bremen
Kontaktdaten:

Freitag 10. März 2006, 13:18

Hallo zusammen!

Ich benutze pickle bzw. cPickle eigentlich schon nen Weilchen und dachte, man würde einfach einmal die "load"-Methode benutzen, um ein serialisiertes Objekt aus einer Datei zu lesen.

Aber nun hab ich folgendes Verhalten festgestellt:

Code: Alles auswählen

>>> import cPickle

>>> f = file("/Library/Application Support/ChrisSek/Report.p", "rb+")
>>> cPickle.load(f)

[{'Action': 'ActionMove', 'ArgDict': {'source': u'/Volumes/Test HD/Src',
 'destination': u'/Volumes/Test HD/Desti'}, 'Type': 0, 'Key':
 'CoreMsgStart', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)}]

>>> cPickle.load(f)

[{'Action': 'ActionMove', 'ArgDict': {'source': u'/Volumes/Test HD/Src', 
'destination': u'/Volumes/Test HD/Desti'}, 'Type': 0, 'Key':
 'CoreMsgStart', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)},

{'Action': 'ActionMove', 'ArgDict': {'source': u'/Volumes/Test HD/Src'},
 'Type': 1, 'Key':
 'CoreMsgMoveSourceEmpty', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)}]

>>> cPickle.load(f)

[{'Action': 'ActionMove', 'ArgDict': {'source': u'/Volumes/Test HD/Src', 
'destination': u'/Volumes/Test HD/Desti'}, 'Type': 0, 'Key':
 'CoreMsgStart', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)},

{'Action': 'ActionMove', 'ArgDict': {'source': u'/Volumes/Test HD/Src'},
 'Type': 1, 'Key':
 'CoreMsgMoveSourceEmpty', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)}, 

{'Action': '', 'ArgDict': {'source': u'/Volumes/Test HD/Src'},
 'Type': 0, 'Key':
 'CoreMsgEnd', 'Time': (2006, 3, 10, 13, 0, 31, 4, 69, 0)}]

>>> cPickle.load(f)

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
EOFError
Wenn ich also einmal load aufrufe, wird mir eine Liste mit einem Element geliefert, bei den nächsten Aufrufen werden dann die fehlenden Einträge der Liste mit eingefügt. Pro Aufruf ein Listen-Element...

Ist das so gewollt? Hab in der Doku nichts dazu gelesen. Vielleicht hab ich aber auch Tomaten auf den Augen - oder so...

Kennt das Problem jemand? Vielleicht noch ein Detail: Ich serialisiere meine Liste mit dem Protokoll 2 (also binär und mit Python 2.4.1) und verwendet beim öffnen der Datei "wb+".

Hab's auch schon mal mit einem String probiert. Also quasi über Protokoll 0 serialisiert und dann den String eingelesen und pickle.loads(s) aufgerufen --> Gleiches Problem!

Vielen Dank und Grüße aus Bremen,
Chris
BlackJack

Freitag 10. März 2006, 22:44

Das sieht so aus, als wenn Du Deine Liste mehrfach mit jeweils einem Element mehr in eine geöffnete Datei schreibst. Das Problem ist dann nicht beim Lesen, sondern beim Schreiben.

Wie schreibst Du denn? Wenn die Liste zum schreiben fertig ist, dann solltest Du die einmal in eine Datei schreiben, welche Du ohne das '+', also nur mit 'wb' öffnest. Übrigens muss man auch das "Textprotokoll" mit 'wb' öffnen. Der Name ist etwas unglücklich gewählt.

Erkärung zum '+' im Dateimodus: Wenn die Datei schon existiert, dann wird sie nicht gelöscht sondern nur zum lesen und schreiben geöffnet. Wenn Du dann Daten reinschreibst, die kürzer als die schon vorhandene Datei sind, dann folgt auf diese Daten immer noch ein Stück des alten Inhalts. Das sollte beim (ent)picklen egal sein, aber ist irgendwie unsauber.
ChrisSek
User
Beiträge: 10
Registriert: Samstag 8. Mai 2004, 13:06
Wohnort: Bremen
Kontaktdaten:

Samstag 11. März 2006, 13:22

BlackJack hat geschrieben:Wie schreibst Du denn? Wenn die Liste zum schreiben fertig ist, dann solltest Du die einmal in eine Datei schreiben, welche Du ohne das '+', also nur mit 'wb' öffnest.
Vielen Dank BlacJack! Ich hab mein Protokoll vorher in eine "normale" Text-Datei geschrieben und dann schnell auf Pickle umgestellt. Und dabei ist's mir passiert, dass ich öfters in eine offene Datei serialisiert habe. Und jedes meiner pickle.dump's wurde einzeln mit pickle.load eingelesen.

Nun klappt's gut - einfach am Ende einmal serialisieren und schon läuft's :D
Antworten