Создание веб-интерфейса для скрипта, выполнение которого занимает 30 минут.

StackOverflow https://stackoverflow.com/questions/2101052

Вопрос

Я написал скрипт Python для обработки некоторых данных из файлов CSV.Выполнение сценария занимает от 3 до 30 минут, в зависимости от размера CSV.

Теперь я хочу добавить к этому веб-интерфейс, чтобы я мог загружать файлы данных CSV из любого места.Я написал базовую страницу загрузки HTTP POST и использовал модуль CGI Python, но через некоторое время сценарий просто отключается.

Сценарий выводит заголовки HTTP в начале и выводит биты данных после итерации по каждой строке CSV.Например, этот оператор печати будет срабатывать примерно каждые 30 секунд.

# at the very top, with the 'import's
print "Content-type: text/html\n\n Processing ... <br />"

# the really long loop.
for currentRecord in csvRecords:
    count = count + 1
    print "On line " + str(count) + " <br />"

Я предполагал, что браузер получит заголовки и будет ждать, поскольку он продолжает получать небольшие фрагменты данных.Но на самом деле, похоже, происходит то, что он вообще не получает никаких данных и Error 504 тайм-аут при получении CSV с большим количеством строк.

Возможно, где-то кэширование происходит?Из журналов,

[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm

Как лучше всего решить эту проблему или нецелесообразно запускать такие сценарии в браузере?

Редактировать:Это скрипт для моего собственного использования — обычно я собираюсь использовать его на своем компьютере, но подумал, что веб-интерфейс может пригодиться во время путешествий или, например, с телефона.Кроме того, скачивать действительно нечего — скрипт, скорее всего, в конце отправит отчет по электронной почте.

Это было полезно?

Решение

Я бы разделил работу так:

  1. URL-адрес веб-приложения, принимающий CSV-файл, отправленный POST.Веб-приложение помещает содержимое CSV в автономную очередь, например таблицу базы данных.Ответ веб-приложения должен представлять собой уникальный идентификатор элемента в очереди (например, используйте столбец с автоматическим увеличением идентификатора).Клиент должен сохранить этот идентификатор для части 3.

  2. Автономное приложение-служба, которое опрашивает очередь на предмет работы и выполняет обработку.По завершении обработки сохраните результаты в другой таблице базы данных, используя уникальный идентификатор в качестве ключа.

  3. URL-адрес веб-приложения, по которому можно получить обработанные результаты. http://server/getresults/uniqueid/.Если обработка завершена (т.уникальный идентификатор находится в таблице базы данных результатов), затем верните результаты.Если не завершено, ответом должен быть код, указывающий на это.Например, пользовательский заголовок HTTP, ответ о состоянии HTTP, тело ответа «ОЖИДАНИЕ» или подобное.

Другие советы

У меня уже была такая ситуация, и я использовал cronjobs.HTTP-скрипт просто записывал в очередь задание, которое необходимо выполнить (БД или файл в каталоге), а задание cron читало его и выполняло это задание.

Вам, вероятно, придется сделать stdout.flush(), поскольку сценарий на самом деле ничего не записывает на веб-сервер, пока вы не запишете данные, необходимые для страничного буфера, чего не происходит до истечения таймаута.

Но правильный способ решить эту проблему, как предлагали другие, - выполнить обработку в отдельном потоке/процессе и показать пользователю автоматически обновляемую страницу, которая показывает статус, с индикатором выполнения или каким-либо другим причудливым визуальным элементом, чтобы сохранить их. от скуки.

См. книгу Рэндала Шварца. Просмотр длительных процессов через CGI.В статье используется Perl, но методика не зависит от языка.

Очень похожий вопрос здесь.Я предлагаю запустить длительный процесс и вернуть пользователю индикатор выполнения на основе ajax.Таким образом, у пользователя есть роскошь веб-интерфейса, а у вас нет тайм-аутов.

imho, лучшим способом было бы запустить независимый скрипт, который где-то публикует обновления (плоский файл, база данных и т. д.).Я не знаю, как создать независимый процесс из Python, поэтому не могу привести примеры кода.

Чтобы показать прогресс на веб-сайте, реализуйте ajax-запрос на страницу, которая считывает эти обновления статуса и, например, показывает красивый индикатор выполнения.

Добавьте что-то вроде setTimeout("refreshProgressBar[...]) или метаобновление для автоматического обновления.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top