die*_*o_c 15 python api performance json flask
我正在烧瓶中写一个返回json的API.每个烧瓶功能都是这种形式
from flask import jsonify
@app.route('/getdata')
def get_data():
data = load_data_as_dict()
return jsonify(data)
Run Code Online (Sandbox Code Playgroud)
如果我返回大量数据,则对此函数的调用大约需要1.7秒.但是,如果我这样做:
from flask import Response
@app.route('/getdata')
def get_data():
data = load_data_as_dict()
data_as_str = json.dumps(data)
return Response(response=data_as_str, status=200, mimetype="application/json"
Run Code Online (Sandbox Code Playgroud)
...该功能在.05秒左右完成.
谁能告诉我为什么jsonify这么慢?返回原始Flask响应有什么问题吗?
kar*_*daj 11
我的猜测是:它与缩进和制作prettyjson转储有很大关系.这是方法定义(我删除了注释以节省空间,完整代码可以在这里找到):
def jsonify(*args, **kwargs):
indent = None
separators = (',', ':')
if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_xhr:
indent = 2
separators = (', ', ': ')
if args and kwargs:
raise TypeError('jsonify() behavior undefined when passed both args and kwargs')
elif len(args) == 1: # single args are passed directly to dumps()
data = args[0]
else:
data = args or kwargs
return current_app.response_class(
(dumps(data, indent=indent, separators=separators), '\n'),
mimetype=current_app.config['JSONIFY_MIMETYPE']
)
Run Code Online (Sandbox Code Playgroud)
dumpssimplejson.dumps如果模块可用则换行,否则使用json.dumps.
我花了一段时间才弄清楚,但 Flask在编码器上jsonify设置了sort_keys参数,并且它似乎默认为True.
添加:
JSON_SORT_KEYS = False
Run Code Online (Sandbox Code Playgroud)
对于较大的 JSON 结构,该配置使我的速度提高了 7 倍。
jsonify()包好了json.dumps()。然而,根据您的水壶应用程序的配置和瓶版本,您正在使用,它可以传递indent=2和separators=(', ', ': ')到json.dumps。(如果您不熟悉这些参数,请参阅https://docs.python.org/3/library/json.html上的精美印刷文档)。
通过这些论点会json.dumps大大减慢速度。使用https://github.com/zemirco/sf-city-lots-json中 181MB的citylots.json文件作为示例数据,这些漂亮的打印参数将MacBook Pro的运行时间从7秒增加到31秒:json.dumps()
>>> import time
>>> import json
>>> citylots = json.load(open('citylots.json'))
>>> start = time.time(); x = json.dumps(citylots); print(time.time() - start)
7.165302753448486
>>> x = None
>>> start = time.time(); x = json.dumps(citylots, indent=2, separators=(', ', ': ')); print(time.time() - start)
31.19125771522522
Run Code Online (Sandbox Code Playgroud)
从Flask 1.0开始,如果发生以下两种情况,就会发生这种昂贵的漂亮打印:
JSONIFY_PRETTYPRINT_REGULAR为,或者TrueFalse(您可以在https://github.com/pallets/flask/blob/1.0.2/flask/json/__init__.py#L309的Flask 1.0.2代码中查看这些条件。)
如果您使用Flask> = 1.0,并且(在调试模式下)需要禁用漂亮打印(可能很特殊),则始终可以jsonify通过复制和粘贴内置jsonify的定义并删除所有漂亮的-打印逻辑:
from flask import current_app
from json import dumps
def jsonify(*args, **kwargs):
if args and kwargs:
raise TypeError('jsonify() behavior undefined when passed both args and kwargs')
elif len(args) == 1: # single args are passed directly to dumps()
data = args[0]
else:
data = args or kwargs
return current_app.response_class(
dumps(data) + '\n',
mimetype=current_app.config['JSONIFY_MIMETYPE']
)
Run Code Online (Sandbox Code Playgroud)
如果你在一个版本瓶之前到1.0,那么漂亮的印刷,而不是发生什么,如果两个:
JSONIFY_PRETTYPRINT_REGULAR为,并且FalseTrue在那些较旧的版本中,不需要重新定义jsonify以消除漂亮的印刷,因为您可以执行以下操作:
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
Run Code Online (Sandbox Code Playgroud)
(或者,如果您使用的是Flask的1.0之前版本,并且只想禁用生产环境中的漂亮打印,则无需更改代码;只需升级到最新版本的Flask。)