コールバックチェーンを漬ける方法
質問
ツイストでユーザー定義の状態マシンを持っています。ユーザーは、さまざまな状態変更のハンドラーを定義できます。これを実装して、コールバックを追加させたねじれた延期を使用して実装できます。ある状態から別の状態に移動するたびに、私は単に適切な延期を解雇します。
プロジェクトの要件の1つは、この州のマシンをすべてのコールバックとともにディスクに保存する機能です。私は単にステートマシンを漬けることができると思ったので、私は完了しますが、ユーザー定義の関数をシリアル化しようとするとピクリーエラーが得られます。
誰かが関数をシリアル化する方法を知っていますか?エラーは、以下のコードサンプルで再現されます。
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)
この最後の行に次のエラーが与えられます。
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
これに対する解決策はありますか?たぶん、ユーザーがコールバックとして追加できる機能の種類を制限する必要がありますか?
ありがとう、
ジョナサン
解決
延期されないようにしないでください。 Twistedによってサポートされていません。たとえあなたが機能しているように見える何かを構築したとしても(そしてそうではありません 全体的に 不可能)、その後のTwistedのリリースは、救われた状態をすべて壊す可能性があります。
延期は、コードを介したイベントの流れを制御するためのものです。それらはアプリケーション状態を保存するためではありません。アプリケーションの状態を保持したい場合は、繰延してシリアル化するものから分離します ただ それ。
これを行う場合、おそらくシリアル化形式にピクルスの使用を避けたいと思うでしょう。ピクルスはデータを保存する良い方法ではありません。これは、Pythonバージョンとライブラリバージョンの変更に非常に敏感な、高い複雑な形式です。スキーマを定義する手段はないので、シリアル化やシリアル化したものを実際に確認することはできません。ピクルスをロードすることとは別に検査することは非常に困難です。そのため(インスタンスを漬けたクラスの名前を変更することにした場合に壊れた場合、データを回復することが大きな面倒です。
他のヒント
Foo/Bar機能を呼び出し可能なクラスインスタンスに置き換えます。
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)