#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. Выходные данные в формате, не совпадающем с тем, который я упомянул в вопросе.