使用Pyro5代理获取对象时出现“不支持的序列化类”

问题描述 投票:0回答:1

我正在更新一些代码以使用 Pyro5(来自 Pyro3),并且看不到如何处理从通过 Pyro 代理访问的方法返回的自定义对象。作为演示,我在文件中创建了两个简单的类

classes.py
Container
有一个返回
Item
实例的方法:

from Pyro5.api import expose

class Container:
    @expose
    def get_item(self):
        return Item()

class Item():
    def __str__(self):
        return "item"

serpent
包可以序列化和反序列化
Item
类型的对象:-

import serpent
from classes import Item

item = Item()
s = serpent.dumps(item)

item2 = serpent.loads(s)
print(item2)

运行此打印,如预期:

{'__class__': 'Item'}

现在我创建一个 Pyro5 守护进程并注册

Container
的实例:

from Pyro5.api import Daemon
from classes import Container
    
daemon = Daemon(host="localhost", port=5555)
daemon.register(Container(),"container")
daemon.requestLoop()

但是当我尝试通过这样的代理获取

Item
的实例时

from Pyro5.api import Proxy

container = Proxy("PYRO:container@localhost:5555")
print(container.get_item())

我遇到异常

Pyro5.errors.SerializeError: unsupported serialized class: classes.Item

如果将

get_item()
改为返回字符串,则一切OK。有没有办法让我的类
Item
被序列化和反序列化,而无需大量额外的自定义代码?既然serpent处理得还可以,而且是Pyro5用的,看来这应该不会太复杂!

python serialization pyro
1个回答
0
投票

既然我已经弄清楚了,就回答我自己的问题,以防将来其他人遇到同样的问题。

Pyro3(我认为 Pyro4 的早期版本)使用 Pickle 来序列化和反序列化对象,这能够重新创建各种自定义对象,包括它们包含的函数。这可能会导致安全问题,因为 Pickle 在从可能不可信的源反序列化对象时会执行任意代码,因此 Pyro4 的最新版本使用 Serpent 代替,而 Pickle 在 Pyro5 中根本不可用。

在我原来的例子中,Serpent 并没有重建一个

Item
对象,而只是一个包含该对象字段的字典。 Pyro 尝试将此字典转换为
Item
对象,但不知道如何转换,因此“不受支持的序列化类”。

推荐的方法(https://pyro5.readthedocs.io/en/latest/clientcode.html#serialization)是使用内置类型而不是自定义类。或者,可以为 Pyro 代理提供将字典转换回所需对象的函数。在我的人造示例中,对象没有实例状态,这非常简单:

from Pyro5.api import Proxy, register_dict_to_class
from classes import Item

def item_dict_to_class(classname, d):
    return Item()
register_dict_to_class("classes.Item", item_dict_to_class)

container = Proxy("PYRO:container@localhost:5555")
print(container.get_item())
© www.soinside.com 2019 - 2024. All rights reserved.