简体   繁体   English

JSON / Base64中的Pyro4编码

[英]Pyro4 Encoding in JSON/Base64

So I have a simple application using Pyro4 (Python Remote Objects). 因此,我有一个使用Pyro4(Python远程对象)的简单应用程序。 There is an exposed class API , and I have a file that calls the function api.parse(input,userid) , which returns some JSON dependent on input. 有一个公开的类API ,我有一个文件调用函数api.parse(input,userid) ,该文件返回一些依赖于输入的JSON。 However, instead of simply returning the result as a string (which it did previously), it returns {'data': 'eyJlcnJvciI6ICJDb21tYW5kIG5vdCByZWNvZ25pc2VkIn0=', 'encoding': 'base64'} , where the base64 is the JSON string that parse should returned. 但是,它不是简单地以字符串形式返回结果(如以前那样),而是返回{'data': 'eyJlcnJvciI6ICJDb21tYW5kIG5vdCByZWNvZ25pc2VkIn0=', 'encoding': 'base64'} ,其中base64是应返回parse的JSON字符串。

I'm very confused as to why this is not working - I have tested it previously and there was no issue, the string was just returned with no weird base64 encoding. 我对为什么它不起作用感到非常困惑-我之前已经对其进行了测试,并且没有问题,该字符串只是使用了奇怪的base64编码返回的。 Only thing I can think of is I have changed networks (School connection to home connection) but I don't think this should be a problem? 我唯一能想到的就是我已经更改了网络(从学校连接到家庭连接),但是我不认为这应该是一个问题吗? I have prepared an MVE of some code that indicates the problem. 我已经准备了一些指示问题的代码的MVE。

testserver.py 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 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"}'

Note - Printing at the stage where prep is applied in parse() gives the expected result b'{"error":"Command not recognised"}' . 注–在parse()应用prep的阶段进行打印会得到预期的结果b'{"error":"Command not recognised"}' I'm using the command python3 -m Pyro4.naming to start the nameserver if that matters as well. 我也使用命令python3 -m Pyro4.naming启动名称服务器(如果同样重要)。 I'm thinking there's probably some global setting/constant I haven't set correctly or something - All responses welcome, thankyou! 我在想可能是某些全局设置/常量未正确设置或其他原因-欢迎所有回复,谢谢!

The default serialization protocol that Pyro uses is serpent, and that is a text-based protocol. Pyro使用的默认序列化协议是蛇,这是基于文本的协议。 This means it cannot transmit binary data (bytes) unless it encodes them to a text format, which it does in the way you discovered. 这意味着它无法传输二进制数据(字节),除非将其编码为文本格式(采用您发现的方式进行编码)。

There's a little helper function ( serpent.tobytes ) available that you could use in your client code that automatically detects and converts the response if needed, see the info box in this paragraph in the manual: https://pythonhosted.org/Pyro4/tipstricks.html?highlight=base64#binary-data-transfer-file-transfer 您可以在客户端代码中使用一些帮助程序功能( serpent.tobytes ),该功能可以根据需要自动检测并转换响应,请参见手册本节中的信息框: https : //pythonhosted.org/Pyro4/ tipstricks.html?highlight = base64#binary-data-transfer-file-transfer

Ofcourse, if you make the data sent by your server strings in the first place, there's no need for this. 当然,如果首先创建由服务器字符串发送的数据,则无需这样做。 (This can't be done if the data really is binary though, such as an image or sound clip or whatever) (但是,如果数据确实二进制的,例如图像或声音片段等,则无法执行此操作)

In your case with the json text it gets transformed into bytes if you encode it. 在您使用json文本的情况下,如果对其encode它将转换为字节 As you discovered there is no need for this at all, just leave it as a string and you won't run into issues. 正如您所发现的,根本不需要这样做,只需将其保留为字符串即可,不会遇到任何问题。 (which leaves me with the question why you're still doing the encode to utf-8 bytes in your client?) (这让我想到了一个问题,为什么您仍然在客户端中对utf-8字节进行编码?)

Turns out Pyro doesn't like trying to send raw bytes - It'd rather convert the bytes to base64 then send it as JSON. 事实证明,Pyro不喜欢尝试发送原始字节-而是将字节转换为base64,然后将其作为JSON发送。 So to fix, I changed: 所以要解决,我改变了:

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

to

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

And put the encode bit in the client. 并将编码位放入客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM