Ошибка сериализации Pyro4: неподдерживаемый сериализованный класс

Я новичок в Pyro4, и мне нужно разобраться в этом, и что может быть лучше, чем попробовать примеры, содержащиеся в пакете Pyro4? Итак, мой первый шаг состоял в том, чтобы просто заставить одну работу работать, это пример «склад». Идея состоит в том, чтобы человек посетил склад и выбрал предметы, которые нужно взять или сохранить. Файл «warehouse.py» содержит информацию о поджигателе, а «visit.py» обеспечивает взаимодействие между человеком и складом.

Сервер имен (в моем случае: Hodor, который запускается pyro4-ns -n Hodor и имеет запись в моем файле hosts в 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

Вот "склад.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()

"человек.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», «укроп» и «рассол», но ни один из них не решил мою проблему. Кроме того, поскольку я читал обо всех проблемах безопасности с некоторыми сериализаторами, я хотел бы сохранить «змей».


person RickJames    schedule 27.06.2016    source источник


Ответы (1)


Ваши исходные файлы неверны. Вы сами их ввели? Откуда вы их взяли? Потому что те, которые вы показываете нам здесь, являются очень старыми версиями этих файлов примеров (3 года!). Эти старые версии действительно больше не будут работать с последними версиями Pyro4 из-за некоторых изменений в механизме сериализатора, которые были сделаны с тех пор.

Самая важная причина, по которой ваш код больше не работает, заключается в том, что в вашем классе «Посетитель» в методах депозита и извлечения код передает экземпляр посетителя пиросервису хранилища. Это невозможно, если вы не скажете Pyro, как сериализовать это. Поскольку это должен быть простой пример, эта сложность здесь не включена, но вы можете прочитать о ней в документации Pyro. Правильная версия примера передает в службу хранилища только имя человека, что позволяет полностью избежать проблемы.

Правильные версии можно скопировать из текущей документации Pyro4< /a> или предоставляется вам в examples/warehouse/phase3 папка исходного дистрибутива Pyro4.

Для полноты, правильные версии следующие. "человек.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.

person Irmen de Jong    schedule 27.06.2016
comment
приятно, большое спасибо! Я получил примеры, погуглив пакет, и теперь, когда вы упомянули об этом, в каталоге написано Pyro4-4.18. - person RickJames; 28.06.2016
comment
Было бы полезнее, если бы вы добавили в свой ответ, как сообщить Pyro, как он может сериализовать/десериализовать класс. У меня есть класс, который состоит из 20~30~ пользовательских классов (сильно вложенных)... - person DGoiko; 03.01.2019
comment
pyro4.readthedocs.io/en/stable/ - person Irmen de Jong; 04.01.2019