[英]Why is flask's jsonify method slow?
我正在烧瓶中写一个返回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响应有什么问题吗?
我的猜测是:它与缩进和制作pretty
json转储有很大关系。 这是方法定义(我删除了注释以节省空间,完整代码可以在这里找到):
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
。
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
文件作为样本数据,这些漂亮的打印参数将json.dumps()
的运行时间从7秒增加到31秒我的MacBook Pro:
>>> 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
由于瓶1.0,这个昂贵的漂亮打印会发生,如果任一 :
JSONIFY_PRETTYPRINT_REGULAR
设置为True
(默认情况下为False
),或者 (您可以在Flask 1.0.2代码中查看这些条件, 网址为https://github.com/pallets/flask/blob/1.0.2/flask/json/__init__.py#L309 。)
如果你使用Flask> = 1.0并且即使在调试模式下也有(可能不寻常)需要禁用漂亮的打印,你总是可以通过复制和粘贴内置的jsonify
定义并删除所有的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']
)
如果您使用的是1.0 之前的 Flask版本,那么如果两者都发生漂亮打印:
JSONIFY_PRETTYPRINT_REGULAR
显式设置为False
(默认情况下为True
),AND 在那些旧版本中,永远不需要重新定义jsonify
以消除漂亮的打印,因为您可以这样做:
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
(或者,如果您使用的是1.0之前版本的Flask并且只想禁用生产中的漂亮打印,则无需更改代码;而只需升级到最新版本的Flask。)
我花了一段时间才弄清楚,但Flask jsonify
在编码器上设置了sort_keys
参数,它似乎默认为True
。
添加:
JSON_SORT_KEYS = False
对于更大的JSON结构,配置为我提供了7倍的加速。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.