Frage

Ich habe eine benutzerdefinierte Statusmaschine in Twisted. Der Benutzer kann Handler für unterschiedliche Zustandsänderungen definieren, die ich mit einem verdrehten aufgeschobenen Aufschub implementieren kann, zu dem ich sie zurück -Rückrufe hinzufügen kann. Immer wenn ich von einem Zustand in einen anderen wechsle, feuere ich einfach die entsprechende Aufschiebung ab.

Eine der Projektanforderungen ist die Möglichkeit, diese Zustandsmaschine zusammen mit allen Rückrufen zu retten. Ich dachte, ich könnte einfach die Statusmaschine übersagen und ich würde fertig sein, aber ich bekomme einen PickleError, wenn ich versuche, benutzerdefinierte Funktionen zu serialisieren.

Kennt jemand eine Möglichkeit, Funktionen zu serialisieren? Der Fehler wird in der folgenden Code -Probe reproduziert:

import pickle
from twisted.internet.utils import defer

def foo(*args):
  def bar():
    print args
  return bar

d = defer.Deferred()
d.addCallback(foo("Hello", "world"))
pickle.dumps(d)

Diese letzte Zeile gibt den folgenden Fehler:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/pickle.py", line 1366, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.5/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 725, in save_inst
    save(stuff)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib/python2.5/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 600, in save_list
    self._batch_appends(iter(obj))
  File "/usr/lib/python2.5/pickle.py", line 615, in _batch_appends
    save(x)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 562, in save_tuple
    save(element)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 562, in save_tuple
    save(element)
  File "/usr/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.5/pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <function bar at 0xb753fe2c>: it's not found as __main__.bar

Gibt es Lösungen dafür? Vielleicht muss ich die Arten von Funktionen einschränken, die Benutzer als Rückrufe hinzufügen können?

Vielen Dank,
Jonathan

War es hilfreich?

Lösung

Versuchen Sie nicht, Aufschiebungen zu überlegen. Es wird nicht von Twisted unterstützt. Auch wenn Sie es schaffen, etwas zu konstruieren, das zu funktionieren scheint (und es ist nicht völlig Unmöglich), eine spätere Veröffentlichung von Twisted könnte Ihren gesamten gespeicherten Zustand brechen.

Aufschubs dient zur Steuerung des Ereignisflusss über Ihren Code. Sie sind nicht für die Aufbewahrung des Anwendungszustands. Wenn Sie Ihren Bewerbungszustand bestehen möchten, trennen Sie ihn von Aufstiegsvorschriften und Serialize nur es.

Wenn Sie dies tun, möchten Sie wahrscheinlich auch die Verwendung von Gurke für das Serialisierungsformat vermeiden. Pickle ist keine gute Möglichkeit, Daten zu speichern. Es ist ein hochkomplexes Format, das sehr empfindlich gegenüber Änderungen in Python -Versionen und Bibliotheksversionen ist. Es hat keine Mittel, um ein Schema zu definieren, sodass Sie nie wirklich sicher sein können, was Sie serialisieren oder was Sie serialisiert haben. Es ist sehr schwierig, eine Gurke getrennt vom Laden zu inspizieren. Wenn sie also jemals bricht (wie es so wird, wenn Sie sich entscheiden, eine Klasse umzubenennen, die Sie eingelegt haben), ist die Wiederherstellung der Daten ein großer Aufwand.

Andere Tipps

Ersetzen Sie die Foo/Bar -Funktionen durch eine Callable -Klasse -Instanz:

class foo(object):
    def __init__(self, *args):
        self.args = args
    def __call__(self):
        print self.args

d = defer.Deferred()
d.addCallback(foo("Hello", "world"))
pickle.dumps(d)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top