JSON/Base64 中的 Pyro4 编码

Pyro4 Encoding in JSON/Base64

所以我有一个使用 Pyro4 的简单应用程序(Python 远程对象)。有一个公开的 class API,我有一个调用函数 api.parse(input,userid) 的文件,其中 returns 一些 JSON 取决于输入。但是,它不是简单地将结果作为字符串返回(它之前这样做),而是 returns {'data': 'eyJlcnJvciI6ICJDb21tYW5kIG5vdCByZWNvZ25pc2VkIn0=', 'encoding': 'base64'} ,其中 base64 是 parse 应该返回的 JSON 字符串。

我很困惑为什么这不起作用 - 我之前测试过它并且没有问题,只是返回的字符串没有奇怪的 base64 编码。我唯一能想到的是我已经改变了网络(学校连接到家庭连接)但我认为这应该不是问题?我已经准备了一些指示问题的代码的 MVE。

testserver.py

import Pyro4;
import json;

@Pyro4.expose
class API:
    def parse(self,buff,userid):
        return prep({"error":"Command not recognised"});

def prep(obj):
    return json.dumps(obj).encode("utf-8");

# Pyro stuff
daemon = Pyro4.Daemon()                # make a Pyro daemon
ns = Pyro4.locateNS()                  # find the name server
uri = daemon.register(API)   # register the greeting maker as a Pyro object
ns.register("testAPI", uri)   # register the object with a name in the name server
daemon.requestLoop()

testclient.py

import Pyro4;
import json;

api = Pyro4.Proxy("PYRONAME:testAPI");
resp = api.parse("whatever","something");
print(resp); # Produces {'data': 'eyJlcnJvciI6ICJDb21tYW5kIG5vdCByZWNvZ25pc2VkIn0=', 'encoding': 'base64'}
# I just want b'{"error":"Command not recognised"}'

注意 - 在 parse() 中应用 prep 的阶段打印会得到预期的结果 b'{"error":"Command not recognised"}'。如果这也很重要,我正在使用命令 python3 -m Pyro4.naming 来启动名称服务器。我在想可能有一些全局 setting/constant 我没有设置正确或什么的 - 欢迎所有回复,谢谢!

事实证明,Pyro 不喜欢尝试发送原始字节 - 它宁愿将字节转换为 base64,然后将其作为 JSON 发送。所以为了修复,我改变了:

def prep(obj):
    return json.dumps(obj).encode("utf-8");

def prep(obj):
    return json.dumps(obj);

并将编码位放入客户端。

Pyro 使用的默认序列化协议是 serpent,这是一个基于文本的协议。这意味着它无法传输二进制数据(字节),除非它按照您发现的方式将它们编码为文本格式。

有一个小辅助函数 (serpent.tobytes),您可以在客户端代码中使用它来自动检测并在需要时转换响应,请参阅手册中本段中的信息框:https://pythonhosted.org/Pyro4/tipstricks.html?highlight=base64#binary-data-transfer-file-transfer

当然,如果你一开始就把服务器发送的数据做成字符串,就没有这个必要了。 (如果数据确实 二进制数据,例如图像或声音剪辑或其他任何东西,则无法完成此操作)

在您使用 json 文本的情况下,如果您 encode 它会转换为 字节 。正如您发现的那样,根本不需要这样做,只需将其保留为字符串,您就不会 运行 遇到问题。 (这给我留下了一个问题,为什么你仍然在你的客户端中对 utf-8 字节进行编码?)