首页 > 解决方案 > 如何加快从 Python-Flask 应用程序返回 20MB Json 文件的速度?

问题描述

我正在尝试调用一个 API,该 API 反过来会从我们的 sqlserver 数据库中触发一个存储过程。我就是这样编码的。

class Api_Name(Resource):

    def __init__(self):
        pass

    @classmethod
    def get(self):
        try:
            engine = database_engine
            connection = engine.connect()
            sql = "DECLARE @return_value int EXEC @return_value = [dbname].[dbo].[proc_name])
            return call_proc(sql, apiname, starttime, connection)
        except Exception as e:
            return {'message': 'Proc execution failed with error => {error}'.format(error=e)}, 400
        pass

call_proc是我从数据库返回 JSON 的方法。

def call_proc(sql: str, connection):
    try:
        json_data = []
        rv = connection.execute(sql)
        for result in rv:
            json_data.append(dict(zip(result.keys(), result)))
        return Response(json.dumps(json_data), status=200)
    except Exception as e:
        return {'message': '{error}'.format(error=e)}, 400
    finally:
        connection.close()

输出的问题在于返回 JSON 的方式及其大小。起初 API 需要 1 分 30 秒:当 return 语句是这样的:

case1: return Response(json.dumps(json_data), status=200, mimetype='application/json')

上网查了一下,发现上面的说法是为了美化JSON。所以我mimetype从回复中删除并将其设为

case2: return Response(json.dumps(json_data), status=200)

API 运行了 30 秒,虽然 JSON 输出没有正确对齐,但它仍然是 JSON。我看到从 API 返回的 JSON 的输出大小接近 20MB。我在邮递员的回复中观察到了这一点:

Status: 200 OK    Time: 29s    Size: 19MB

Json输出的区别:

情况1:

[   {
        "col1":"val1",
        "col2":"val2"
    },
    {
        "col1":"val1",
        "col2":"val2"
    }
]

案例2:

[{"col1":"val1","col2":"val2"},{"col1":"val1","col2":"val2"}]

上述两种情况的输出差异会有所不同吗?如果是这样,我该如何解决这个问题?如果没有区别,有什么办法可以进一步加快速度并进一步减少运行时间,比如压缩我返回的 JSON 吗?

标签: pythonjsonpython-3.xflaskflask-sqlalchemy

解决方案


您可以使用gzip压缩来使纯文本的重量从兆字节到千字节。甚至为此使用烧瓶压缩库。
另外我建议使用ujsondump()加快通话速度。

import gzip

from flask import make_response
import ujson as json


@app.route('/data.json')
def compress():
    compression_level = 5  # of 9 max
    data = [
        {"col1": "val1", "col2": "val2"},
        {"col1": "val1", "col2": "val2"}
    ]
    content = gzip.compress(json.dumps(data).encode('utf8'), compression_level)
    response = make_response(content)
    response.headers['Content-length'] = len(content)
    response.headers['Content-Encoding'] = 'gzip'
    return response

文档:


推荐阅读