【问题标题】:twisted: How to send and receive the same object with Perspective Broker?twisted:如何使用 Perspective Broker 发送和接收相同的对象?
【发布时间】:2012-02-18 19:24:04
【问题描述】:

我有一个简单的 '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 导入 pb

class aClass(pb.Copyable):
    pass

当我运行上面的代码时,我得到这个错误: twisted.spread.jelly.InsecureJelly:模块 builtin 不允许(在 builtin.RemoteClass 类型中)。

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

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

【问题讨论】:

    标签: python serialization twisted perspective broker


    【解决方案1】:

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

    python foo.py
    

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

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

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

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

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

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

    【讨论】:

    • 我已经从 server.py 中删除了类并将它们放入 amodule.py,这是我的新文件内容: server.py: codepad.org/fRZTwgKI amodule.py: codepad.org/h9rON50E 没有改变,我仍然得到果冻错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 2016-01-21
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多