我正在使用 Python 3.8,并且希望将数据字典保存到 JSON 文件中,该文件一次性压缩在存档中,最好仅使用 Python 标准库。例如,这意味着我的数据保存在文件 data.json
中,该文件包含在存档
compressed_data.zip
中。现在,这就是我所得到的:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: GPL-3.0-or-later
# Python Standard Library imports
import json
import zlib
# Prepare some data
data: dict = {
"common_name": "Brongersma's short-tailed python",
"scientific_name": "Python brongersmai",
"length": 290
}
# Save data to a JSON file
with open("data.json", "w", encoding="utf-8") as output_JSON_file:
json.dump(data, output_JSON_file, ensure_ascii=False, indent=4)
# Open saved JSON then compress it
with open ("data.json", "r", encoding="utf-8") as input_JSON_file:
data: dict = json.load(input_JSON_file)
# Data needs to be saved as bytes to be compressed
data_bytes: bytes = json.dumps(data, indent=4).encode("utf-8")
compressed_data = zlib.compress(data_bytes, level=zlib.Z_BEST_COMPRESSION)
with open ("compressed_data.zip" , "wb") as output_zlib_file:
output_zlib_file.write(compressed_data)
这不会产生我想要的结果,因为(a)
它首先保存JSON文件,打开它,然后将数据保存到一个压缩文件中,最后在磁盘上有two文件; (b) 压缩文件是压缩的 数据,但不是可以在任何通用 GUI 压缩/解压缩程序中打开的 ZIP 文件中的 JSON 文件。 所以我的问题是:
.json
文件永远不会接触磁盘,只有
.zip
文件接触磁盘)
并将存档直接解压缩到 Python 中的字典中?
zlib
库或 ZIP 文件。
其他高压缩比方法也可以。 谢谢!
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: GPL-3.0-or-later
# Python's internal `zipfile` module
import json
import zipfile
# Prepare some data
data: dict = {
"common_name": "Brongersma's short-tailed python",
"scientific_name": "Python brongersmai",
"length": 290
}
# Use the `zipfile` module
# `compresslevel` was added in Python 3.7
with zipfile.ZipFile("compressed_data.zip", mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as zip_file:
# Dump JSON data
dumped_JSON: str = json.dumps(data, ensure_ascii=False, indent=4)
# Write the JSON data into `data.json` *inside* the ZIP file
zip_file.writestr("data.json", data=dumped_JSON)
# Test integrity of compressed archive
zip_file.testzip()
此解决方案使用 Python 标准库的内部
zipfile
模块
。关键是
zip_file.writestr()
,它允许您基本上写入 ZIP 文件内部的文件。 如果还有其他解决方案,请分享!
import json
from codecs import getwriter
from typing import IO
from zipfile import ZIP_DEFLATED, ZipFile
class ZipFileWrapper(ZipFile):
def open(self, name="data", mode="r", pwd=None, **kwargs):
return super().open(name=name, mode=mode, pwd=pwd, **kwargs)
def read(self):
return super().read(name="data")
def _json_dump_bytes(fp: IO, obj):
StreamWriter = getwriter("utf-8")
return json.dump(fp=StreamWriter(fp), obj=obj)
def json_dump_zip(fp: IO, obj):
with ZipFileWrapper(
fp, mode="w", compression=ZIP_DEFLATED, compresslevel=9
) as zip_file:
with zip_file.open(mode="w") as _fp:
json_dump_bytes(fp=_fp, obj=obj)
def json_load_zip(fp: IO):
with ZipFileWrapper(fp, mode="r") as zip_file:
return json.load(zip_file)
用途:
obj = {"foo": "bar"}
with open("my_file.zip", "wb") as f:
json_dump_zip(fp=f, obj=obj)
with open("my_file.zip, "rb") as f:
loaded_obj = json_load_zip(fp=f)
详情:
它的工作原理是利用
codec._StreamWriter
作为中介,直接从字符串输入写入类似字节的 IO。这避免了无法直接转储到 zip 文件的原因 - 因为
json.dump
写入 unicode,而不是 ZipFile
所需的字节。实施细节:
我已将 zip 中的 json 文件命名为
"data"
。这是因为对于我的实现,我只需要压缩单个 json 文件,并且文件的名称与我的目的无关。随心所欲地编辑!