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 字节进行编码?)
所以我有一个使用 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 字节进行编码?)