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

9ceoxa92  于 2023-10-21  发布在  Python
关注(0)|答案(6)|浏览(139)

我经常发送一个巨大的JSON字符串(在Flask中使用jsonify)到我的网页,所以我想减少数据。最简单的选择可能是删除所有的换行符和空格字符,但只是给你一个给予这样的例子:
普通jsonify:361KB
删除所有换行符和空格字符:118 KB(哇)。
压缩原始文件:35 KB(双哇)。
所以我基本上想知道是否有一个简单的方法来接近35 KB。到目前为止,我还没有找到一个可以用python和JavaScript轻松实现的解决方案。
现在,我每秒发送大约4- 5 MB的数据,这是-你猜对了-有点”太多了。

6uxekuva

6uxekuva1#

  • 老问题,但我正在寻找这个,这是谷歌上的第一个结果。* 链接到里昂的答案有一个解决方案,而不是 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,所以浏览器会自动删除。
在JavaScript中使用jQuery Ajax请求进行解码时,与标准请求没有任何特别的区别:

$.ajax({
    url: '/data.json',
    dataType: 'json',
    success: function(data) {
        console.log(data);
    }
})

请注意,此代码段压缩然后发送长内容。您应该考虑压缩内容所需的时间(特别是在这种情况下,我们有很长的内容),所以一定要设置一个适当的压缩级别,不需要更多的时间来压缩+发送比发送长内容。
我的用例是,我从一个缓慢的连接发送大的内容,所以我有所有的好处,在发送之前压缩内容。

flseospp

flseospp2#

Web请求确实支持GZip,你可以在Python中实现它。
这是一个问过同样问题的人。How to use Content-Encoding: gzip with Python SimpleHTTPServer
根据 flask 压缩回收
首选的解决方案是让服务器(如Nginx)自动压缩静态文件。
但你可以在 flask 中做到这一点:https://github.com/colour-science/flask-compress
如果你使用gzip,你将不需要删除换行符和白色空格,但是如果你仍然想这样做,那么根据flask文档,你可以通过将JSONIFY_PRETTYPRINT_REGULAR设置为false来禁用漂亮打印。

xe55xuns

xe55xuns3#

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

from flask import Flask
from flask_compress import Compress

app = Flask(__name__)
Compress(app)
ddrv8njm

ddrv8njm4#

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

然后在你的app中:

from flask import Flask
from gzip_compress import GzipCompress

app = Flask(__name__)
GzipCompress(app)

你可以设置你的gzip压缩级别和压缩的最小响应大小。它还包括对gzip支持和响应代码的其他检查。

p1iqtdky

p1iqtdky5#

suvigyavijay's answer的衍生品,没有使用笨拙的类io.BytesIO()gzip.GzipFile(他做了很多繁重的工作, prop )。
注意。我认为这适用于所有请求。

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
wwodge7n

wwodge7n6#

选择的答案谈到了Flask-Compress,这是伟大的压缩。然而,你可能会看到你的JSON仍然没有去掉新的行和缩进(特别是当你在调试模式下检查输出时)。
由于JSONIFY_PRETTYPRINT_REGULAR已被弃用,要使其在后续Flask版本(2.2+)中工作,请设置:

app.json.compact = True

我花了一些时间才找到这个设置,所以在这里添加这个,以避免搜索它。

相关问题