要求:具有2-3层嵌套的Python对象,包含基本数据类型,如整数、字符串、列表和字典。(没有日期等),需要在redis中根据键存储为json。为了减少内存占用,将json压缩为字符串的最佳方法是什么?目标对象不是很大,平均只有1000个小元素,转换为JSON时大约有15000个字符。
例如:
>>> my_dict
{'details': {'1': {'age': 13, 'name': 'dhruv'}, '2': {'age': 15, 'name': 'Matt'}}, 'members': ['1', '2']}
>>> json.dumps(my_dict)
'{"details": {"1": {"age": 13, "name": "dhruv"}, "2": {"age": 15, "name": "Matt"}}, "members": ["1", "2"]}'
### SOME BASIC COMPACTION ###
>>> json.dumps(my_dict, separators=(',',':'))
'{"details":{"1":{"age":13,"name":"dhruv"},"2":{"age":15,"name":"Matt"}},"members":["1","2"]}'
1/有没有其他更好的方法来压缩json以节省redis中的内存(也可以确保之后的轻量级解码)。
2/候选人的msgpack http://msgpack.org/会有多好?
3/我是否也应该考虑像泡菜这样的选项?
发布于 2013-03-21 00:34:26
我们只是使用gzip
作为一个压缩器。
import gzip
import cStringIO
def decompressStringToFile(value, outputFile):
"""
decompress the given string value (which must be valid compressed gzip
data) and write the result in the given open file.
"""
stream = cStringIO.StringIO(value)
decompressor = gzip.GzipFile(fileobj=stream, mode='r')
while True: # until EOF
chunk = decompressor.read(8192)
if not chunk:
decompressor.close()
outputFile.close()
return
outputFile.write(chunk)
def compressFileToString(inputFile):
"""
read the given open file, compress the data and return it as string.
"""
stream = cStringIO.StringIO()
compressor = gzip.GzipFile(fileobj=stream, mode='w')
while True: # until EOF
chunk = inputFile.read(8192)
if not chunk: # EOF?
compressor.close()
return stream.getvalue()
compressor.write(chunk)
在我们的用例中,我们将结果存储为文件,正如您可以想象的那样。要只使用内存中的字符串,也可以使用cStringIO.StringIO()
对象作为文件的替代。
发布于 2018-08-27 05:31:40
基于上面@Alfe的answer,这里有一个版本,它将内容保存在内存中(用于网络I/O任务)。我还做了一些更改以支持Python3。
import gzip
from io import StringIO, BytesIO
def decompressBytesToString(inputBytes):
"""
decompress the given byte array (which must be valid
compressed gzip data) and return the decoded text (utf-8).
"""
bio = BytesIO()
stream = BytesIO(inputBytes)
decompressor = gzip.GzipFile(fileobj=stream, mode='r')
while True: # until EOF
chunk = decompressor.read(8192)
if not chunk:
decompressor.close()
bio.seek(0)
return bio.read().decode("utf-8")
bio.write(chunk)
return None
def compressStringToBytes(inputString):
"""
read the given string, encode it in utf-8,
compress the data and return it as a byte array.
"""
bio = BytesIO()
bio.write(inputString.encode("utf-8"))
bio.seek(0)
stream = BytesIO()
compressor = gzip.GzipFile(fileobj=stream, mode='w')
while True: # until EOF
chunk = bio.read(8192)
if not chunk: # EOF?
compressor.close()
return stream.getvalue()
compressor.write(chunk)
要测试压缩,请尝试:
inputString="asdf" * 1000
len(inputString)
len(compressStringToBytes(inputString))
decompressBytesToString(compressStringToBytes(inputString))
发布于 2019-12-10 03:24:32
我在不同的二进制格式(MessagePack,BSON,Ion,Smile CBOR)和压缩算法(Brotli,Gzip,XZ,Zstandard,bzip2)之间做了一些广泛的比较。
对于我用于测试的JSON数据,将数据保留为JSON并使用Brotli压缩是最好的解决方案。Brotli有不同的压缩级别,所以如果您要长时间地保存数据,那么使用高级别的压缩可能是值得的。如果您坚持的时间不长,那么较低的压缩级别或使用Zstandard可能是最有效的。
Gzip很简单,但几乎可以肯定的是,要么更快,要么提供更好的压缩,或者两者兼而有之。
你可以在这里阅读我们调查的全部细节:Blog Post
https://stackoverflow.com/questions/15525837
复制相似问题