我在烧瓶中写了一个返回json的API。每个烧瓶功能的形式为
from flask import jsonify
@app.route('/getdata')
def get_data():
data = load_data_as_dict()
return jsonify(data)
如果我返回大量数据,则调用此函数大约需要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"
...该功能在.05秒左右完成。
有谁能告诉我为什么jsonify
慢得多?返回原始Flask响应有什么问题吗?
答案 0 :(得分:9)
我的猜测是:它与缩进和pretty
json转储有很大关系。这是方法定义(我删除了注释以节省空间,可以找到完整的代码here):
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']
)
如果模块可用,则 dumps
换simplejson.dumps
,否则使用json.dumps
。
答案 1 :(得分:5)
jsonify()
只包裹json.dumps()
。但是,根据您的Flask应用程序的配置以及您正在使用的Flask版本,它可能会将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上将json.dumps()
的运行时间从7秒增加到31秒:
>>> 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
从Flask 1.0开始,如果 ,这种昂贵的漂亮打印将会发生:
JSONIFY_PRETTYPRINT_REGULAR
至True
(默认情况下为False
),或(您可以在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']
)
如果你在Flask 之前的版本到1.0,那么如果两者都发生漂亮打印:
JSONIFY_PRETTYPRINT_REGULAR
到False
(默认情况下为True
),和在那些旧版本中,从来没有必要重新定义jsonify
以消除漂亮的打印,因为您可以这样做:
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
(或者,如果您使用的是1.0版之前的Flask,并且只想禁用生产中的漂亮打印,那么就无需更改代码;相反,只需升级到最新版本的Flask。)
答案 2 :(得分:3)
我花了一段时间才弄清楚,但是Flask (xenial)vash@localhost:~/python/stack_overflow/test$ ls
1_file_b.py 2_file_e.py 3_file_a.py 4_file_c.py 5_file_d.py
在编码器上设置了jsonify
参数,看来它默认为sort_keys
。
添加:
True
通过配置,我可以将大型JSON结构的速度提高7倍。