我在Twisted中有一个用户定义的状态机。用户可以为不同的状态更改定义处理程序,我通过使用Twisted延迟实现,我让他们添加回调。每当我从一个州迁移到另一个州时,我只需触发适当的延期。
项目要求之一是能够将此状态机及其所有回调保存到磁盘。我以为我可以简单地挑选状态机并且我已经完成了,但是当我尝试序列化用户定义的函数时,我得到了一个PickleError。
有人知道序列化函数的方法吗?错误在以下代码示例中重现:
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
这有什么解决方案吗?也许我需要限制用户可以添加为回调的函数类型?
谢谢,
乔纳森
答案 0 :(得分:2)
不要试图腌制Deferreds。 Twisted不支持它。即使你设法构建一些似乎有用的东西(并且它不是完全不可能),Twisted的后续版本可能会破坏你所有已保存的状态。
延迟用于控制代码中的事件流。它们不是用于存储应用程序状态。如果您想要保留您的应用程序状态,请将其与任何Deferreds分开并序列化只是。
执行此操作时,您可能还希望避免使用pickle作为序列化格式。 Pickle不是存储数据的好方法。它是一种高度复杂的格式,对Python版本和库版本的更改非常敏感。它无法定义架构,因此您永远无法确定要序列化的内容或序列化的内容。单独检查一个泡菜是非常困难的,所以如果它一直打破(如果你决定重命名一个你腌制过的实例的那个),那么恢复数据是一个很大的麻烦。
答案 1 :(得分:0)
用可调用的类实例替换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)