cub*_*ube 10 python sockets json
我打开了一个套接字,我想从中读取一些json数据.问题是json
标准库中的模块只能从字符串解析(load
只读取整个文件并调用loads
内部)它甚至看起来模块内部的所有方式都取决于参数是字符串.
这是套接字的一个真正问题,因为你永远无法将它全部读取为字符串,并且在实际解析之前你不知道要读取多少字节.
所以我的问题是:是否有(简单而优雅)的解决方法?是否有另一个可以递增地解析数据的json库?值得自己写吗?
编辑:这是XBMC jsonrpc api.没有消息信封,我无法控制格式.每条消息可以在一行或多行上.我可以编写一些简单的解析器,它只需要某种形式的getc函数并使用它来提供它s.recv(1)
,但这不是一个非常pythonic的解决方案,我有点懒,这样做:-)
编辑:鉴于您没有定义协议,这没有用,但在其他上下文中可能有用。
假设它是一个流 (TCP) 套接字,您需要实现自己的消息帧机制(或使用现有的更高级别的协议来实现)。一种直接的方法是将每条消息定义为一个 32 位整数长度字段,后跟那么多字节的数据。
Sender:取JSON包的长度,用struct
模块打包成4个字节,在socket上发送,然后发送JSON包。
Receiver:反复从socket中读取,直到至少有4个字节的数据,用于struct.unpack
解包长度。从套接字读取,直到您至少有那么多数据,这就是您的 JSON 数据包;剩下的就是下一条消息的长度。
如果在某个时候您想通过同一个套接字发送由 JSON 以外的内容组成的消息,您可能需要在长度和数据负载之间发送消息类型代码;恭喜你,你又发明了另一个协议。
另一种稍微更标准的方法是 DJB 的Netstrings协议;它与上面提出的系统非常相似,但使用文本编码的长度而不是二进制;它由Twisted等框架直接支持。
如果您要从 HTTP 流获取 JSON,请使用Content-Length
标头来获取 JSON 数据的长度。例如:
import httplib
import json
h = httplib.HTTPConnection('graph.facebook.com')
h.request('GET', '/19292868552')
response = h.getresponse()
content_length = int(response.getheader('Content-Length','0'))
# Read data until we've read Content-Length bytes or the socket is closed
data = ''
while len(data) < content_length or content_length == 0:
s = response.read(content_length - len(data))
if not s:
break
data += s
# We now have the full data -- decode it
j = json.loads(data)
print j
Run Code Online (Sandbox Code Playgroud)
你想要的是 ijson,一个增量 json 解析器。它可以在这里找到: https: //pypi.python.org/pypi/ijson/。用法应该很简单(从该页面复制):
import ijson.backends.python as ijson
for item in ijson.items(file_obj):
# ...
Run Code Online (Sandbox Code Playgroud)
(对于那些喜欢独立的东西的人 - 从某种意义上说,它只依赖于标准库:我昨天写了一个关于 json 的小包装 - 但只是因为我不了解 ijson。它的效率可能要低得多。)
编辑:因为我发现事实上我的方法(的 cythonized 版本)比 ijson 更有效,所以我将其打包为一个独立的库 - 也请参阅这里的一些粗略基准:http ://pietrobattiston.it/jsaone
归档时间: |
|
查看次数: |
16567 次 |
最近记录: |