在python中将数据块加载到.json(或字典)中



我想用请求流下载一个。gz文件,同时解压缩流文件。

我要做的代码位是:

import requests
import zlib
url = "https://something"
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):  
data = d.decompress(chunk)

我还想将未压缩的数据块转换为json/dictionary。但是,由于数据的块部分不能保证是完整的json/字典格式,因此我无法将数据加载到字典或json格式中。然后,我想将数据位发送到将数据插入mongodb数据库的管道。

我想这样做:

import requests
import json
import pandas as pd
import zlib
url = "https://something"
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):  
data = d.decompress(chunk)
#something like the line down there
yield json.load(data)
#or something like 
yield df.to_dict(data)

是否有办法将这些未压缩的块加载到json或将它们转换为字典?或者,以其他方式将此数据加载到mongodb?

仅供参考,我的压缩文件约为90MB,未压缩文件约为1.2 GB。

我的压缩文件约为90MB,未压缩文件约为1.2 GB

如果你被允许使用外部模块,我建议看看json-stream外部模块,作为

json.load()不同,json-stream可以JSON数据类文件对象。这有以下好处:

  • 它不要求整个json文档预先进入内存
  • 它可以在整个文档加载完成之前开始生成数据
  • 它只需要足够的内存来保存当前正在解析的数据

由于json_stream.loads例外于类文件对象,如果您想从内存加载,则需要使用io.StringIO,请考虑以下示例

import io
import json_stream
data = '["uno","dos","tres"]'
data_io = io.StringIO(data)
for i in json_stream.load(data_io):
print(i)

输出
uno
dos
tres

注意io.BytesIOio.StringIO也可能用于其他地方类似文件的预期,不仅在json_stream.loadio是内置模块,更多信息请参考io文档。

我找到了一个解决我的问题,这是为我工作,但不确定它是否会为其他人工作。我想我应该在这里分享一下,以防万一。

import json
import requests
import zlib
url = "helloworld.com"
data = ""
flag = 0
d = zlib.decompressobj(zlib.MAX_WBITS | 16)
with requests.get(url, stream=True) as r:
r.raise_for_status()
for chunk in r.iter_content(chunk_size=128):  
datum = d.decompress(chunk)
try:
data+= datum.decode('utf-8')
if flag == 1:
data = data[data.find('"first_key"'):]
data = "[{" + data
flag = 0

if data.count('"first_key"')>=2:
#here -8 to get the last instance of the first_key of an element, might change depending upon the format
location = data.rfind('"first_key"')-8 
data1 = data[:location]
if data1[0] == "[":
data1+="]"
data2 = json.loads(data1)
data = "[{" + data[data.rfind('"first_key"'):]
yield data2
except:
data = ""
flag = 1
continue

最新更新