Каков самый быстрый способ преобразовать фрейм данных pandas в json?

#python #python-3.x #pandas

#питон #python-3.x #панды

Вопрос:

Я запускаю API, который запускает процедуру хранения в таблице Sqlserver в фрейм данных, а затем возвращает результат пользователю в виде Json. Ниже приведен код, который я написал, который работает.

 def call_proc(sql: str, connection):
    """
    :param sql: Call store procedure
    :return: Successful request - 200. Bad Request - 400.
    """
    try:
        dataframe = pd.read_sql_query(sql, con=connection)
        print(f'duration to run sql: {datetime.datetime.now() - begin}')
        result = dataframe.reset_index(drop=True).to_json(orient="records")
        result = json.loads(result)
        print(f'duration to prepare result: {datetime.datetime.now() - begin}')
        return result, 200
    except Exception as e:
        return {'message': '{error}'.format(error=e)}, 400
    finally:
        logger.info('Closing the connection.')
        connection.close()
 

Строка: sql содержит оператор вызова процедуры хранения.

Результат выглядит следующим образом

 [
    {
        "col1":"val1",
        "col2":"val2",
    },
    {
        "col1":"val1",
        "col2":"val2",
    }
]
 

Выходные данные процедуры хранения содержат 20000 строк.
Когда я запускаю API, который вызывает вышеупомянутый метод, время отклика API составляет 30 секунд, что намного медленнее по сравнению с моим требованием.
Есть ли более быстрый способ преобразовать фрейм данных в Json?

Попытка 2: я также попытался выполнить цикл по фрейму данных, как показано ниже, и вернуть json.

 dataframe = pd.read_sql_query(sql, con=connection)
query_result, json_result = "", {}
for ir in dataframe.itertuples():
    query_result = str(ir[1])
json_result = json.loads(query_result)
return json_result, 200
 

Но в результате получается ошибка:
{ "message": "Expecting value: line 1 column 1 (char 0)" }

Я напечатал время, затраченное на выполнение sql и подготовку json, используя операторы печати, и инструкции печати из моего журнала можно найти ниже. Продолжительность выполнения sql в sql server studio составляет 2 секунды

 duration to run sql: 0:00:06.666858
duration to prepare result: 0:00:08.328360
 

Попытка 3: Использование соединения и SQL

 json_data = []
rv = connection.execute(sql)
for result in rv:
    json_data.append(dict(zip(result.keys(), result)))
return json.dumps(json_data), 200
 

Даже это занимает столько же времени, сколько и при использовании фрейма данных pandas.

Комментарии:

1. Может быть, попробовать какие-то другие варианты, такие как df.to_dict ? Также попробуйте сделать все за один шаг (возврат xxxxx) вместо 2 шагов (сохранение и загрузка). Только мои 2 цента

2. @loaTzimas Я добавил вторую попытку. Можете ли вы сказать мне , что там происходит не так ?

3. Хм, я не совсем понимаю, почему это произошло. Вы измерили время выполнения вашего SQL-запроса? Может быть, задержка и есть.

4. Чтобы подготовить json, в среднем требуется 25-26 секунд. Чтобы вернуть подготовленный результат, потребуется еще 4-5 секунд.

5. Но где время, затрачиваемое на это? В sql или в python? Это очень важно. Если это в sql, то вы не сможете многое сделать с изменениями в python

Ответ №1:

Вы

  • использование Pandas для загрузки SQL в фрейм данных (который включает в себя вывод типа данных и округление)
  • затем с помощью Pandas превратить это в строку JSON
  • затем используйте библиотеку JSON Python, чтобы превратить эту строку обратно в список
  • затем возвращая это из вашего представления, которое снова строит его.

Вместо этого вы должны

  • используйте собственное SQL-соединение, которое у вас уже есть для выполнения запроса
  • добавьте строки из этого результата в список
  • верните этот список

Комментарии:

1. Я пытался сделать так, как вы сказали. Вы можете найти его в попытке 3. Код по-прежнему выполняется в течение 35 секунд.

2. Вы можете попробовать более быстрый сериализатор JSON, такой как orjson , но в целом: профилируйте свой код, чтобы увидеть, где находится фактическое узкое место.

Ответ №2:

Вы можете использовать функцию .to_json для преобразования вашего фрейма данных в пример JSON.

 import json
df = pd.DataFrame(
    [["a", "b"], ["c", "d"]],
    index=["row 1", "row 2"],
    columns=["col 1", "col 2"],
)

result = df.to_json(orient="split")
parsed = json.loads(result)
json.dumps(parsed, indent=4)  
{
    "columns": [
        "col 1",
        "col 2"
    ],
    "index": [
        "row 1",
        "row 2"
    ],
    "data": [
        [
            "a",
            "b"
        ],
        [
            "c",
            "d"
        ]
    ]
}
 

Комментарии:

1. Выходные данные в формате, не совпадающем с тем, который я упомянул в вопросе.