Pyro4序列化错误:不支持的序列化类

时间:2016-06-27 10:00:30

标签: python windows serialization pyro

我是Pyro4的新手,需要深入了解它,还有什么比试用Pyro4包中的示例更好的方法?所以我的第一步是简单地完成一个工作,这就是“仓库”的例子。这个想法是让一个人访问仓库并选择要采取或存储的物品。 文件“warehouse.py”包含Pyro deamon信息,而“visit.py”则包含人员和仓库之间的交互。

名称服务器(在我的情况下:Hodor,由pyro4-ns -n Hodor启动并在C:\Windows\System32\drivers\etc中的主机文件中有一个条目)和“warehouse.py”必须在两个单独的终端窗口中运行。每次我通过第三个终端窗口中的“visit.py”开始通信时,首先它会工作并询问我是否要存储某些内容。如果我这样做,我会收到错误消息:
“Pyro4.errors.SerializeError:不支持的序列化类: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',但没有一个能解决我的问题。此外,由于我阅读了一些序列化程序的所有安全问题,我想保留“蛇”。

1 个答案:

答案 0 :(得分:0)

您的源文件错误。你自己打字了吗?你是从哪里得到的?因为你在这里展示的那些是这些示例文件的旧版本(3年前!)这些旧版本确实不再使用最新版本的Pyro4,因为自从之后对序列化器机制进行了一些更改然后

您的代码不再起作用的最重要原因是因为您的访问者&#39;访客&#39; class,在存放和检索方法中,代码将Visitor实例传递给Warehouse pyro服务。除非你告诉Pyro如何序列化它,否则这是不可能的。由于这只是一个简单的例子,这里不包括这种复杂性,但你可以在Pyro的文档中阅读它。该示例的正确版本仅将人员的名称传递给仓库服务,从而完全避免了该问题。

可以从the current Pyro4 documentation复制正确的版本,或者在Pyro4源代码发布的examples/warehouse/phase3文件夹中为您提供。

为完整起见,正确的版本如下。 &#34; person.py&#34;:

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)

然后,&#34; visit.py&#34;:

# 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)

最后,&#34; warehouse.py&#34;:

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配合使用。