cPickle-Protokolle

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
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Mittwoch 18. Februar 2009, 17:19

Bei Verwendung von cPickle.dump wird protocol=2 empfohlen. Ich kann das aber nicht benutzen, weil mein Programm (welches mit protocol=1 glatt durchläuft) dann abstürtzt. Hier ein Beispiel, das hoffentlich repräsentativ ist:

Code: Alles auswählen

import cPickle as p
class FOO(object):
  #
  def __new__(cls,geninfo=None,pkdatei=None):
    print "\nNeues FOO: geninfo =",geninfo, "pkdatei =",pkdatei
    #
    if geninfo==None:
      assert not pkdatei==None
      speicher_eing = open(pkdatei+'.bid','rb')
      self = p.load(speicher_eing)
      speicher_eing.close()
    else:
      self = object.__new__(cls)
      self.var = int(geninfo)
    return self
  #
  def speichere(self,pkdatei="FOO"):
    speicher_ausg = open(pkdatei+'.bid','wb')
    p.dump(self,speicher_ausg,protocol=1) #anscheinend fehlerlos
    #p.dump(self,speicher_ausg,protocol=2) #empfohlen, aber falsch
    speicher_ausg.close()
  #
  def __str__(self): return "FOO(%i)"%self.var


foo = FOO(geninfo=42)
print "1. foo =", foo
#
foo.speichere(pkdatei="testfoo")
del foo
if 'foo' in dir(): print "2. foo =", foo
#
foo = FOO(pkdatei="testfoo")
print "3. foo =", foo
Mache ich etwas falsch oder ist protocol=2 nur manchmal verwendbar?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 18. Februar 2009, 17:35

Goswin hat geschrieben:Ich kann das aber nicht benutzen, weil mein Programm (welches mit protocol=1 glatt durchläuft) dann abstürtzt.
Ist es ein Segfault oder warum sagst du uns nicht was der Traceback sagt?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 18. Februar 2009, 17:51

@Leonidas: Es kracht beim ``assert`` weil `__new__` beim Entpicklen anscheinend nochmal ohne Argumente aufgerufen wird.

Code: Alles auswählen

$ ./forum2.py

Neues FOO: geninfo = 42 pkdatei = None
1. foo = FOO(42)

Neues FOO: geninfo = None pkdatei = testfoo

Neues FOO: geninfo = None pkdatei = None
Traceback (most recent call last):
  File "forum2.py", line 114, in <module>
    foo = FOO(pkdatei="testfoo")
  File "forum2.py", line 91, in __new__
    self = p.load(speicher_eing)
  File "forum2.py", line 89, in __new__
    assert not pkdatei==None
AssertionError
@Goswin: Eine Funktion die zwei Argumente entgegennimmt und bei einem Aufruf jeweils eins davon ignoriert und jeweils etwas anderes macht, ist IMHO ein "code smell", weil das im Grunde *zwei* Funktionen sind, die nur zusammengeworfen wurden. Was spricht denn gegen folgendes (ungetestet):

Code: Alles auswählen

class Foo(object):
    FILENAME_EXTENSION = '.bid'
    
    def __init__(self, value):
        self.value = value
    
    def __str__(self):
        return '%s(%s)' % (self.__class__.__name__, self.var)
    
    def save(self, base_name):
        with open(base_name + self.FILENAME_EXTENSION) as pickle_file:
            pickle.dump(self, pickle_file, 2)
    
    @staticmethod
    def load(base_name):
        with open(base_name + self.FILENAME_EXTENSION) as pickle_file:
            return pickle.load(pickle_file)
Benutzeravatar
snafu
User
Beiträge: 5465
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 18. Februar 2009, 18:41

@goswin:

Warum willst du eigentlich zwanghaft __new__() nutzen? War ja auch schon im anderen Thread so, wo dir auch Tipps gegeben wurden wie es weniger unkonventionell geht.
shcol (Repo | Doc | PyPi)
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Donnerstag 19. Februar 2009, 11:51

snafu hat geschrieben:@goswin: Warum willst du eigentlich zwanghaft __new__() nutzen?
Ich will nicht "zwanghaft __new__() nutzen", sondern Python lernen. Mein Programm lief schon vor meiner Fragestellung korrekt durch; ich mache derzeit ein Refactoring und untersuche, ob __new__ eine brauchbare Alternative zur Fabrikfunktion ist. Ich möchte davon ausgehen, dass neue Features in Python von den Python-Entwicklern gründlich durchdiskutiert wurden und nicht vollends nutzlos sind.
BlackJack hat geschrieben:@Goswin: Eine Funktion die zwei Argumente entgegennimmt und bei einem Aufruf jeweils eins davon ignoriert und jeweils etwas anderes macht, ist IMHO ein "code smell", weil das im Grunde *zwei* Funktionen sind, die nur zusammengeworfen wurden.
Ja, an diesem Argument ist etwas dran. Die beiden Funktionen gehören freilich insofern zusammen, als dass das gelieferte Objekt in beiden Fällen absolut identisch ist, und es dem Client-Code völlig egal ist, wie das Objekt erstellt worden ist. Ob es auf eine oder die andere Weise entsteht, könnte unter Umständen nur daran liegen, dass der Speicherplatz irgendeinmal knapp und die Speicherungsdatei deshalb plötzlich gelöscht wurde. Da das Programm im Falle von geninfo<>None UND pkfile<>None das Objekt durch Einlesen erstellen soll, sollte ich im Beispielcode eigentlich nach der Existenz von pkdatei fragen und nicht nach geninfo==None. Aber das Problem mit protocol=2 bleibt auch so bestehen.

Nebenbei: Dank deiner Antwort erfahre ich, dass es in Python 2.5 auch ein Keyword "with" gibt. Man weiß wirklich nie, was man durch eine Forumsanfrage alles neues dazulernen kann :) !
Zuletzt geändert von Goswin am Donnerstag 19. Februar 2009, 13:59, insgesamt 2-mal geändert.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Donnerstag 19. Februar 2009, 11:59

Hoi Goswin,

das mit dem __new__, obwohl man Dir auseinandergesetzt hat, warum, es nur in Ausnahmesituationen sinnvoll ist, irritiert mich auch.

Wenn Du die geladene Instanz unbedingt noch manipulieren möchtest, bevor Du sie zurückgibst, könntest Du statt @staticmethod auch @classmethod nehmen und self bzw. cls übergeben und in der load()-Funktion manipulieren. Warnung: Auch das sollte man nicht leichtfertig tun, denn sonst weiß ein Nutzer der Klasse - momöglich auch Du nach drei Monaten, wenn sich das Ding nicht mehr so verhält, wie erwartet - nicht was da im Hintergrund läuft, ohne Code zu lesen. ;-)

HTH
Christian
Benutzeravatar
Goswin
User
Beiträge: 361
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen

Donnerstag 19. Februar 2009, 13:51

CM hat geschrieben:Das mit dem __new__, obwohl man dir auseinandergesetzt hat, warum es nur in Ausnahmesituationen sinnvoll ist, irritiert mich auch.
CM, Ich möchte dich sicher nicht irritieren.

Nicht jeder User muss sich mit jeden Themenstrang auseinandersetzen, und ich habe bereits deutlich hervorgehoben, dass es mir nicht darum geht, mein Programm zum Laufen zu bringen. Wenn ich mich persönlich dafür interessiere, die Anwendungsmöglichkeiten von __new__ auszuloten und meine Erfahrungen in einem Forumsthema mit anderen auszutauschen, dann darf ich das doch, oder?
Antworten