python - 如何加快从 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 吗?
解决方案
您可以使用gzip
压缩来使纯文本的重量从兆字节到千字节。甚至为此使用烧瓶压缩库。
另外我建议使用ujson来dump()
加快通话速度。
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
文档:
推荐阅读
- python - 机器利用率的调度问题
- java - java - 从java中的jfreechart中的范围轴获取域轴后,如何在域轴上设置刻度单位?
- gitlab - 即使代码上传到托管平台检索到错误,Gitlab 作业也会成功
- python - 使用复合 PseudoVoigt 模型时出现 NameError
- css - 如何将 sass 直接编译成 web 主机上的 css 文件?
- system.reactive - Rx 合并运算符和并行执行
- extjs - 如何防止触发器切断这么多的文本字段?
- java - java中的泛型类和equals()方法:类型安全
- single-sign-on - 使用 SAML 和 Kerberos 的 SSO
- html - 如何在水平和垂直滚动时使标题固定