簡體   English   中英

為什么燒瓶的jsonify方法很慢?

[英]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=2separators=(', ', ': ')傳遞給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
  • 當前請求不是XHR請求

在那些舊版本中,永遠不需要重新定義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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM