Django работает слишком медленно при обработке исключений
В представлении, в котором происходит исключение, обрабатывается большой словарь, содержащий около ~350K записей. Исключение представляет собой KeyError.
Из журналов CProfile видно, что Django пытается итерировать словарь, чтобы получить данные о возвратах к трассировке.
Вот упрощенный код из представления:
@login_required
def export_plan_data(request):
try:
form = PortfolioPlanningForm(request.GET, user=request.user)
file = get_export_file(user=request.user, form.get_params()) # This is where the exception happens
filename = f"Plan {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}.xlsx"
response = HttpResponse(file, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
response["Content-Disposition"] = f"attachment; filename={filename}"
return response
except Exception as e:
return JsonResponse({"error": "An error occurred while exporting the data"}, status=500)
Если я заключаю все представление в блок try/except и возвращаю свой пользовательский ответ при возникновении исключения, он возвращается примерно за 10 секунд, но если я удаляю блок try/except и позволяю Django обработать исключение, это занимает около 5 минут.
Вот дамп Cprofile:
Это вполне логично, особенно если DEBUG
имеет значение True
. В этом случае Django генерирует страницу, которая покажет обратную трассировку, а чтобы сделать ее более удобной, она даже добавляет содержание параметров всех вызовов функций.
Это означает, что если ваш трассировщик где-то передаст ваш словарь с этими 350k+ записями, то он теперь начнет печатать их, чтобы добавить их в ответ. Действительно, вы можете посмотреть на ответ об ошибке, расширить трассировку, а затем расширить переменные. Они не определяются, когда вы расширяете список переменных, но Django готовит полный ответ.