twisted:如何使用Perspective Broker发送和接收相同的对象?

时间:2012-01-25 15:49:05

标签: python serialization twisted perspective broker

我有一个简单的'echo'PB客户端和服务器,客户端将一个对象发送到服务器,该对象将同一个对象回送给客户端:

客户:

from twisted.spread import pb
from twisted.internet import reactor
from twisted.python import util
from amodule import aClass

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8282, factory)
d = factory.getRootObject()

d.addCallback(lambda object: object.callRemote("echo", aClass()))
d.addCallback(lambda response: 'server echoed: '+response)
d.addErrback(lambda reason: 'error: '+str(reason.value))
d.addCallback(util.println)

d.addCallback(lambda _: reactor.stop())
reactor.run()

服务器:

from twisted.application import internet, service
from twisted.internet import protocol
from twisted.spread import pb
from amodule import aClass

class RemoteClass(pb.RemoteCopy, aClass):
    pass
pb.setUnjellyableForClass(aClass, RemoteClass)

class PBServer(pb.Root):
    def remote_echo(self, a):
        return a

application = service.Application("Test app")

# Prepare managers
clientManager = internet.TCPServer(8282, pb.PBServerFactory(PBServer()));
clientManager.setServiceParent(application)

if __name__ == '__main__':
    print "Run with twistd"
    import sys
    sys.exit(1)

aClass是一个实现Copyable的简单类:     来自twisted.spread import pb

class aClass(pb.Copyable):
    pass

当我运行上面的代码时,我收到此错误:     twisted.spread.jelly.InsecureJelly:模块内置不允许(类型内置 .RemoteClass)。

实际上,该对象被发送到服务器没有任何问题,因为它在服务器端使用pb.setUnjellyableForClass(aClass,RemoteClass)进行保护,但是一旦它返回到客户端,就会引发该错误。

我正在寻找一种方法来轻松地在两个同伴之间发送/接收我的对象。

1 个答案:

答案 0 :(得分:3)

透视代理在通过网络讨论类时按名称识别类。类的名称部分来自定义它的模块。从命令行(即“主脚本”)运行的文件中定义类的一个棘手问题是它们最终可能会出现一个令人惊讶的名称。当你这样做时:

python foo.py

Python为foo.py中的代码提供的模块名称不是"foo",正如人们所期望的那样。相反,它类似于"__main__"(这就是if __name__ == "__main__":技巧起作用的原因。)

但是,如果您的应用程序的某些其他部分稍后尝试从foo.py导入某些内容,则Python 重新评估其内容以创建 new 模块名为"foo"

此外,一个进程的"__main__"模块中定义的类可能与另一个进程的"__main__"模块中定义的类无关。在您的示例中就是这种情况,其中__main__.RemoteClass在您的服务器进程中定义,但客户端进程的RemoteClass模块中没有__main__

因此,PB混淆了,无法完成对象传输。

解决方案是将主脚本中的代码量保持在最低限度,特别是永远不要在其中定义名称(没有类,没有函数定义)。

然而,另一个问题是期望可以通过PB发送RemoteCopy而无需额外准备。可以发送Copyable,在对等体上创建RemoteCopy,但这不是对称关系。您的客户还需要通过进行类似(或不同)pb.setUnjellyableForClass电话来实现此目的。