flask插件之 flask-compress

1. flask-compress

flask-compress 插件可以使用gzip算法压缩flask服务返回的响应数据,压缩后,数据的体积更小,网络传播速度更快,如果你的服务返回的数据体积比较大,使用flask-compress将极大提高网络传输的效率,却并不用付出太多的cpu投入。

安装方法

pip install flask-compress

2. 使用示例

为了更好的展示flask-compress 的作用,我先不使用这个插件返回一个体积比较大的数据

from flask import Flask, jsonify
from flask_compress import Compress

app = Flask(__name__)
# Compress(app)

@app.route('/json')
def get_json_data():
    data = {
        'name': '小明',
        'age': 14
    }
    lst = []
    for i in range(1000):
        lst.append(data)

    return jsonify(lst)

if __name__ == '__main__':
    app.run(port=5500)

启动服务后在浏览器里访问 http://127.0.0.1:5500/json , 服务端返回的数据大小为33002 字节,接下来,打开注释掉的Compress(app) 这一行代码,对返回数据进行gzip压缩, 重启服务,在浏览器里再次访问前面的地址,通过开发者工具可以查看压缩后服务端返回的数据只有49字节。

之所以有这么大的压缩比,是因为构造的数据很适合压缩,列表里的数据每一项都是相同的,才会有这么搞的压缩比,这只是认为构造的个例。

3. flask-compress 参数如何设置

3.1 COMPRESS_REGISTER

COMPRESS_REGISTER 参数默认为True, 表示对所有视图返回的数据进行压缩,如果你不希望如此,可以将它设置为False,然后只在自己希望压缩的视图上进行注册

from flask import Flask, jsonify
from flask_compress import Compress

app = Flask(__name__)
app.config['COMPRESS_REGISTER'] = False
compress = Compress(app)

@app.route('/json')
@compress.compressed()
def get_json_data():
    data = {
        'name': '小明',
        'age': 14
    }
    lst = []
    for i in range(1000):
        lst.append(data)

    return jsonify(lst)

if __name__ == '__main__':
    app.run(port=5500)

3.2 COMPRESS_MIMETYPES

COMPRESS_MIMETYPES 规定了对那些类型的返回数据进行压缩,默认的范围是

['text/html', 'text/css', 'text/xml',
  'application/json',
   'application/javascript']

response 的content-type如果不在这些类型中,则不会进行压缩。

3.3 COMPRESS_MIN_SIZE

这个参数默认值是500字节,如果返回数据的大小没有超过这个数值则不会进行gzip压缩,gzip压缩会消耗服务器的性能,如果数据量太小,就没有必要进行压缩。

其他的参数,可以参考其源码进行设置。

4. flask-compress 实现原理

flask 的插件都有着相同的构建方法,使用他们时,你写的代码都类似于下面的样子

app = Flask(__name__)
app.config['COMPRESS_REGISTER'] = False
compress = Compress(app)

来看一下Compress 的初始化函数

    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

继续追踪阅读init_app 方法,你就能够找到事情的真相

    def init_app(self, app):
        defaults = [
            ('COMPRESS_MIMETYPES', ['text/html', 'text/css', 'text/xml',
                                    'application/json',
                                    'application/javascript']),
            ('COMPRESS_LEVEL', 6),
            ('COMPRESS_BR_LEVEL', 4),
            ('COMPRESS_BR_MODE', 0),
            ('COMPRESS_BR_WINDOW', 22),
            ('COMPRESS_BR_BLOCK', 0),
            ('COMPRESS_DEFLATE_LEVEL', -1),
            ('COMPRESS_MIN_SIZE', 500),
            ('COMPRESS_CACHE_KEY', None),
            ('COMPRESS_CACHE_BACKEND', None),
            ('COMPRESS_REGISTER', True),
            ('COMPRESS_ALGORITHM', ['br', 'gzip', 'deflate']),
        ]

        for k, v in defaults:
            app.config.setdefault(k, v)

        backend = app.config['COMPRESS_CACHE_BACKEND']
        self.cache = backend() if backend else None
        self.cache_key = app.config['COMPRESS_CACHE_KEY']

        algo = app.config['COMPRESS_ALGORITHM']
        if isinstance(algo, str):
            self.enabled_algorithms = [i.strip() for i in algo.split(',')]
        else:
            self.enabled_algorithms = list(algo)

        if (app.config['COMPRESS_REGISTER'] and
                app.config['COMPRESS_MIMETYPES']):
            app.after_request(self.after_request)

看最后一行代码

app.after_request(self.after_request)

在flask-compress 内部,利用app的after_request方法为flask服务注册了一个钩子,当请求结束时就会执行Comporess 的after_request 方法,其他的flask插件的实现原理大体也是如此。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案