【问题标题】:Pyro4 Encoding in JSON/Base64JSON/Base64 中的 Pyro4 编码
【发布时间】:2017-03-01 21:30:54
【问题描述】:

所以我有一个使用 Pyro4(Python 远程对象)的简单应用程序。有一个公开的类API,我有一个文件调用函数api.parse(input,userid),它返回一些依赖于输入的JSON。但是,它不是简单地将结果作为字符串返回(它以前做过),而是返回 {'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 来启动名称服务器。我在想可能有一些全局设置/常数我没有正确设置或其他什么 - 欢迎所有回复,谢谢!

【问题讨论】:

  • 也只是一个注释 - 是的,我可以解码 base64 字符串,但我想知道 为什么 它这样做(如果我编写代码来解码 base64 并且它切换回来我必须重新调试它)。

标签: python json network-programming remoteobject pyro


【解决方案1】:

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

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

当然,如果您一开始就通过服务器字符串发送数据,则没有必要这样做。 (如果数据确实是 二进制的,则无法做到这一点,例如图像或声音剪辑或其他)

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

【讨论】:

  • 感谢您提供更清晰、更详细的答案。数据稍后通过套接字连接(需要字节)发送,所以我想一步完成所有处理。
  • 好吧,还有一件事:你为什么在你的服务器中进行 json 编码?只需按原样返回响应对象,让客户端决定如何处理它!
  • 稍微复杂一些。我有这个服务器/客户端配置,然后发送到另一个客户端。例如:Datastore ---(Pyro)---> Frontend ---(Socket)---> Client,因此我不直接使用 RMI 对象。
【解决方案2】:

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

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

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

并将编码位放入客户端。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-15
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 2021-11-30
    • 2011-03-08
    相关资源
    最近更新 更多