[英]How to compress/minimize size of JSON/Jsonify with Flask in Python?
我经常向我的网页发送一个巨大的 JSON 字符串(在 Flask 中使用 jsonify),所以我想减少数据。 最简单的选择可能是删除所有换行符和空格字符,但只是给你一个例子:
普通 jsonify:361KB
删除所有换行符和空格字符:118KB(哇)。
压缩原始文件:35KB(双哇)。
所以我基本上想知道是否有一种简单的方法可以接近 35KB。 到目前为止,我找不到可以在 python 和 javascript 中轻松实现(解压缩)的解决方案。
现在,我每秒发送大约 4-5MB 的数据,这 - 你猜对了 - “一点点”太多了。
老问题,但我正在搜索这个,这是谷歌上的第一个结果。 Leon 的答案链接有一个不适用于 Flask 的解决方案,而且它也很旧。 现在使用 Python 3,我们可以使用标准库(和 Flask)在几行代码中完成所有工作:
from flask import make_response, json
import gzip
@app.route('/data.json')
def compress():
very_long_content = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}]
content = gzip.compress(json.dumps(very_long_content).encode('utf8'), 5)
response = make_response(content)
response.headers['Content-length'] = len(content)
response.headers['Content-Encoding'] = 'gzip'
return response
使用gzip.compress我们直接压缩了一个字节字符串,它需要一个字节字符串作为输入。 然后,作为来自 Leon 的链接,我们进行了自定义响应,说明内容是 gzip,因此浏览器将自行解压缩。
对于使用 JQuery ajax 请求在 Javascript 中解码,与标准请求没有任何特别的区别:
$.ajax({
url: '/data.json',
dataType: 'json',
success: function(data) {
console.log(data);
}
})
请注意,此代码段压缩然后发送长内容。 您应该考虑压缩内容所需的时间(特别是在我们有很长的内容的情况下),因此请确保设置适当的压缩级别,压缩 + 发送所需的时间不会超过发送时间内容很长。
我的用例是我从慢速连接发送大内容,所以我有所有的好处在发送之前压缩内容。
Web 请求确实支持 GZip,您可以在 python 中实现它。
这是问那个确切问题的人。 如何使用 Content-Encoding: gzip 和 Python SimpleHTTPServer
根据烧瓶压缩回购
首选的解决方案是让服务器(如 Nginx)自动为您压缩静态文件。
但是你可以在烧瓶中做到: https : //github.com/colour-science/flask-compress 。
如果您使用 gzip 路线,您将不需要删除换行符和空格,但是如果您仍然想要根据烧瓶文档,您可以通过将 JSONIFY_PRETTYPRINT_REGULAR 设置为 false 来禁用漂亮打印。
如果您正在寻找一个库来帮助通过 Gzip(或 Brotli)提供压缩内容,请尝试flask-compress 。 这很简单; 这可能就是您需要做的所有事情:
from flask import Flask
from flask_compress import Compress
app = Flask(__name__)
Compress(app)
受Ripper346's answer 的启发,而不是为所有路线/视图手动编写它。 最好添加一个片段(与库的外部依赖相比),它将在发送之前压缩响应。
将以下内容添加到您的应用程序文件或任何适合的地方(例如 gzip_compress.py):
import gzip
from io import BytesIO
from flask import request
class GzipCompress:
def __init__(self, app, compress_level=9, minimum_size=100):
self.app = app
self.compress_level = compress_level
self.minimum_size = minimum_size
self.app.after_request(self.after_request)
def after_request(self, response):
accept_encoding = request.headers.get('Accept-Encoding', '')
if response.status_code < 200 or \
response.status_code >= 300 or \
response.direct_passthrough or \
len(response.get_data()) < self.minimum_size or \
'gzip' not in accept_encoding.lower() or \
'Content-Encoding' in response.headers:
return response
gzip_buffer = BytesIO()
gzip_file = gzip.GzipFile(mode='wb',
compresslevel=self.compress_level,
fileobj=gzip_buffer)
gzip_file.write(response.get_data())
gzip_file.close()
response.set_data(gzip_buffer.getvalue())
response.headers['Content-Encoding'] = 'gzip'
response.headers['Content-Length'] = len(response.get_data())
return response
然后在您的应用中:
from flask import Flask
from gzip_compress import GzipCompress
app = Flask(__name__)
GzipCompress(app)
您可以设置 gzip 压缩级别和最小响应大小以进行压缩。它包括对 gzip 支持和响应代码的其他检查。
suvigyavijay 的答案的衍生,没有使用尴尬的类, io.BytesIO()
或gzip.GzipFile
(尽管他做了很多繁重的工作,道具)。
笔记。 我认为这适用于所有请求。
import flask, gzip
app = flask.Flask(__name__)
@app.after_request
def compress(response):
accept_encoding = flask.request.headers.get('accept-encoding','').lower()
if response.status_code<200 or response.status_code>=300 or response.direct_passthrough or 'gzip' not in accept_encoding or 'Content-Encoding' in response.headers: return response
content = gzip.compress(response.get_data(), compresslevel=9) # 0: no compression, 1: fastest, 9: slowest. Default: 9
response.set_data(content)
response.headers['content-length'] = len(content)
response.headers['content-encoding'] = 'gzip'
return response
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.