0

我有一个简单的 '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 的简单类: from twisted.spread import pb

class aClass(pb.Copyable):
    pass

当我运行上面的代码时,我得到这个错误:twisted.spread.jelly.InsecureJelly: Module builtin not allowed (in type builtin .RemoteClass)。

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

我正在寻找一种方法来获得一种在两个对等方之间发送/接收我的对象的简单方法。

4

1 回答 1

3

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

python foo.py

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

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

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

所以,PB搞混了,无法完成对象传输。

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

RemoteCopy然而,另一个问题是不需要额外准备就可以通过 PB 发送a 的期望。Copyable可以发送A ,RemoteCopy在对等体上创建 a,但这不是对称关系。您的客户还需要通过拨打类似(或不同)的pb.setUnjellyableForClass电话来允许这样做。

于 2012-01-25T16:07:44.507 回答