如何使用Python中的Flask压缩/最小化JSON / Jsonify的大小?

时间:2015-05-11 10:35:19

标签: javascript python json flask

我经常向我的网页发送一个巨大的JSON字符串(在Flask中使用jsonify),所以我想减少数据。最简单的选择可能是删除所有换行符和空格字符,但只是举个例子:

正常jsonify:361KB
删除所有换行符和空格字符:118KB(哇) 压缩原始文件:35KB(双哇)。

所以我基本上想知道是否有一种简单的方法来接近35KB。到目前为止我找不到一个解决方案,我可以在python和javascript(解压缩)中轻松实现。

现在,我每秒发送大约4-5MB的数据,这是 - 你猜对了 - “有点”太多了。

4 个答案:

答案 0 :(得分:16)

旧问题,但我一直在搜索,这是Google上的第一个结果。指向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);
    }
})

请注意,此代码段将进行压缩,然后发送长内容。您应该考虑压缩内容所花费的时间(特别是在这种情况下,我们的内容很长),因此请确保设置适当的压缩级别,压缩+发送不需要比发送花费更多时间内容太长了。

我的用例是,我通过慢速连接发送了大内容,因此我有在发送内容之前对其进行压缩的所有好处。

答案 1 :(得分:10)

Web请求确实支持GZip,您可以在python中实现它。

这是有人问过这个问题。 How to use Content-Encoding: gzip with Python SimpleHTTPServer

但是既然你正在使用flask,那么有一个组件可以做到: https://flask-compress.readthedocs.org/en/latest/ 如果您想对特定视图进行压缩,这里也是一个示例代码段。 http://flask.pocoo.org/snippets/122/

如果你使用gzip路线,则不需要删除换行符和空格,但是如果你仍然想根据烧瓶文档,你可以通过将JSONIFY_PRETTYPRINT_REGULAR设置为false来禁用漂亮的打印。 http://flask.pocoo.org/docs/0.10/config/

答案 2 :(得分:1)

如果您正在寻找一个库来帮助通过Gzip(或Brotli)提供压缩内容,请尝试flask-compress。很简单;这可能就是您需要做的:

from flask import Flask
from flask_compress import Compress

app = Flask(__name__)
Compress(app)

答案 3 :(得分:1)

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支持和响应代码的其他检查。