Pyro4 Serialize Error : unsupported serialized class

Pyro4 Serialize Error : unsupported serialized class

我是 Pyro4 的新手,需要深入了解它,还有什么比试用 Pyro4 包中包含的示例更好的方法呢?所以我的第一步是简单地做一个工作,就是例子"warehouse"。这个想法是让一个人参观仓库并选择要拿走或储存的物品。 文件 "warehouse.py" 包含 Pyro 守护程序信息,而 "visit.py" 使人与仓库之间的交互正常工作。

名称服务器(在我的例子中:Hodor,它由 pyro4-ns -n Hodor 启动并且在我的主机文件 C:\Windows\System32\drivers\etc 中有一个条目)并且 "warehouse.py" 必须是 运行 在两个单独的终端 windows。每次我在第三个终端 window 中通过 "visit.py" 开始通信时,首先它会工作并询问我是否要存储一些东西。如果这样做,我会收到错误消息:
"Pyro4.errors.SerializeError: unsupported serialized class: person.Visitor"

  File "visit.py", line 10, in <module>
    janet.visit(warehouse)
  File "C:\Users\RickJames\Pyro_other_machine\person.py", line 14, in visit
    self.retrieve(warehouse)
  File "C:\Users\RickJames\Pyro_other_machine\person.py", line 25, in retrieve
    warehouse.take(self, item)
  File "C:\Python34\lib\site-packages\Pyro4\core.py", line 171, in __call__
    return self.__send(self.__name, args, kwargs)
  File "C:\Python34\lib\site-packages\Pyro4\core.py", line 428, in _pyroInvoke
    raise data
Pyro4.errors.SerializeError: unsupported serialized class: person.Visitor

这里是"warehouse.py":

from __future__ import print_function
import Pyro4
import person


class Warehouse(object):
    def __init__(self):
        self.contents=["chair","bike","flashlight","laptop","couch"]

    def list_contents(self):
        return self.contents

    def take(self, person, item):
        self.contents.remove(item)
        print("{0} took the {1}.".format(person.name, item))

    def store(self, person, item):
        self.contents.append(item)
        print("{0} stored the {1}.".format(person.name, item))


def main():
    warehouse=Warehouse()
    Pyro4.Daemon.serveSimple(
            {
                warehouse: "warehouse"
            },
            host = "Hodor",
            ns=True)

if __name__=="__main__":
    main()

"person.py":

from __future__ import print_function
import sys

if sys.version_info<(3,0):
    input=raw_input


class Visitor(object):
    def __init__(self, name):
        self.name=name
    def visit(self, warehouse):
        print("This is {0}.".format(self.name))
        self.deposit(warehouse)
        self.retrieve(warehouse)
        print("Thank you, come again!")
    def deposit(self, warehouse):
        print("The warehouse contains:", warehouse.list_contents())
        item=input("Type a thing you want to store (or empty): ").strip()
        if item:
            warehouse.store(self, item)
    def retrieve(self, warehouse):
        print("The warehouse contains:", warehouse.list_contents())
        item=input("Type something you want to take (or empty): ").strip()
        if item:
            warehouse.take(self, item)

最后 "visit.py":

import sys
import Pyro4
import Pyro4.util
from person import Visitor

warehouse=Pyro4.Proxy("PYRONAME:warehouse")
janet=Visitor("Janet")
henry=Visitor("Henry")
janet.visit(warehouse)
henry.visit(warehouse)

我知道 Pyro4 默认使用序列化程序 "serpent"。我尝试切换到 'marshal'、'json'、'dill' 和 'pickle',但其中的 none 解决了我的问题。另外,由于我了解了一些序列化程序的所有安全问题,所以我想保留 "serpent"。

你的源文件有误。你自己输入的吗?你从哪里弄来的?因为您在这里向我们展示的是那些示例文件的非常旧的版本(3 年前!)这些旧版本确实不再适用于最新版本的 Pyro4,因为从那时起对序列化程序机制进行了一些更改。

您的代码不再工作的最重要原因是因为在您的 'Visitor' class 中,在存款和检索方法中,代码将 Visitor 实例传递给 Warehouse pyro服务。这是不可能的,除非你告诉 Pyro 如何序列化它。由于这是一个简单的示例,因此这里不包含复杂性,但您可以在 Pyro 的文档中阅读相关内容。该示例的正确版本仅将此人的 姓名 传递给仓库服务,从而完全避免了该问题。

可以从 Pyro4 源代码分发的 the current Pyro4 documentation, or is provided for you in the examples/warehouse/phase3 文件夹中复制正确的版本。

为了完整起见,正确的版本如下。 "person.py":

from __future__ import print_function
import sys

if sys.version_info < (3, 0):
    input = raw_input


class Person(object):
    def __init__(self, name):
        self.name = name

    def visit(self, warehouse):
        print("This is {0}.".format(self.name))
        self.deposit(warehouse)
        self.retrieve(warehouse)
        print("Thank you, come again!")

    def deposit(self, warehouse):
        print("The warehouse contains:", warehouse.list_contents())
        item = input("Type a thing you want to store (or empty): ").strip()
        if item:
            warehouse.store(self.name, item)

    def retrieve(self, warehouse):
        print("The warehouse contains:", warehouse.list_contents())
        item = input("Type something you want to take (or empty): ").strip()
        if item:
            warehouse.take(self.name, item)

然后,"visit.py":

# This is the code that visits the warehouse.
import sys

import Pyro4
import Pyro4.util
from person import Person


sys.excepthook = Pyro4.util.excepthook

warehouse = Pyro4.Proxy("PYRONAME:example.warehouse")
janet = Person("Janet")
henry = Person("Henry")
janet.visit(warehouse)
henry.visit(warehouse)

最后,"warehouse.py":

from __future__ import print_function
import Pyro4


@Pyro4.expose
class Warehouse(object):
    def __init__(self):
        self.contents = ["chair", "bike", "flashlight", "laptop", "couch"]

    def list_contents(self):
        return self.contents

    def take(self, name, item):
        self.contents.remove(item)
        print("{0} took the {1}.".format(name, item))

    def store(self, name, item):
        self.contents.append(item)
        print("{0} stored the {1}.".format(name, item))


def main():
    Pyro4.Daemon.serveSimple(
        {
            Warehouse: "example.warehouse"
        },
        ns=True)


if __name__ == "__main__":
    main()

这些在 Pyro 4.45 上运行良好。