簡體   English   中英

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

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM