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

Я написал скрипт на 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

Какой лучший способ решить эту проблему, или не подходит для запуска таких сценариев в браузере?

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

Ответы [ 6 ]

12 голосов
/ 20 января 2010

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

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

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

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

5 голосов
/ 20 января 2010

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

4 голосов
/ 20 января 2010

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

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

2 голосов
/ 20 января 2010

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

2 голосов
/ 20 января 2010

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

1 голос
/ 20 января 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...