Подтвердить что ты не робот

Как запустить длительные (бесконечные) процессы Python?

Недавно я начал экспериментировать с использованием Python для веб-разработки. До сих пор я имел успех с помощью Apache с mod_wsgi и веб-картой Django для Python 2.7. Однако я столкнулся с некоторыми проблемами с постоянно работающими процессами, обновлением информации и т.д.

Я написал script я вызываю "daemonManager.py", который может запускать и останавливать все или отдельные петли обновления python (Должен ли я назвать их демонами?). Он делает это путем разметки, затем загружает модуль для выполнения определенных функций и запускает бесконечный цикл. Он сохраняет PID файл в /var/run, чтобы отслеживать процесс. Все идет нормально. Проблемы, с которыми я столкнулся, следующие:

  • Время от времени один из процессов просто прекратится. Я проверяю ps утром, и процесс просто исчез. Ошибок не было зарегистрировано (я использую модуль logging), и я рассказываю обо всех исключениях, о которых я могу думать и регистрировать их. Также я не думаю, что эти процессы выхода имеют какое-то отношение к моему коду, потому что все мои процессы запускают совершенно другой код и выходят с довольно похожими интервалами. Конечно, я ошибаюсь. Нормально ли, что процессы Python просто умирают после того, как они работают в течение нескольких дней/недель? Как мне решить эту проблему? Должен ли я написать еще один демон, который периодически проверяет, продолжают ли другие демоны? Что делать, если этот демон останавливается? Я не понимаю, как с этим справиться.

  • Как я могу программно узнать, работает ли процесс еще или нет? Я сохраняю файлы PID в /var/run и проверяю, существует ли файл PID для определения того, запущен ли процесс. Но если процесс просто умирает из-за неожиданных причин, PID файл останется. Поэтому я должен удалять эти файлы каждый раз, когда процесс выходит из строя (пару раз в неделю), какой вид поражения цели. Наверное, я могу проверить, работает ли процесс в PID в файле, но что, если начался другой процесс и был назначен PID мертвого процесса? Мой демон подумал бы, что процесс работает нормально, даже если он давно мертв. Снова я не понимаю, как с этим бороться.

Любой полезный ответ о том, как лучший запускать бесконечные процессы Python, надеюсь, также пролить свет на вышеупомянутые проблемы, я буду принимать


Я использую Apache 2.2.14 на машине Ubuntu.
Моя версия Python - 2.7.2

4b9b3361

Ответ 1

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

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

Мое любимое решение http://supervisord.org/

Используя такую ​​систему, как supervisord, вы в основном пишете обычный python script, который выполняет задачу, застревая в "бесконечном" цикле.

#!/usr/bin/python

import sys
import time

def main_loop():
    while 1:
        # do your stuff...
        time.sleep(0.1)

if __name__ == '__main__':
    try:
        main_loop()
    except KeyboardInterrupt:
        print >> sys.stderr, '\nExiting by user request.\n'
        sys.exit(0)

Написание вашего script таким образом упрощает и упрощает разработку и отладку (вы можете легко запустить/остановить его в терминале, наблюдая за выходом журнала, когда события разворачиваются). Когда придет время для запуска в производство, вы просто определяете конфигурацию супервизора, которая вызывает ваш script (здесь пример полный для определения "программы", большая часть которого необязательна: http://supervisord.org/configuration.html#program-x-section-example).

У супервизора есть набор параметров конфигурации, поэтому я не буду перечислять их, но я скажу, что он специально решает проблемы, которые вы описываете:

  • фоновый/режим демона
  • ПИД-отслеживание (может быть настроено на перезапуск процесса, если он неожиданно завершится)
  • Обычно регистрируется в script (обработчик потока, если используется модуль протоколирования, а не печать), но пусть диспетчер перенаправляет файл к вам.

Ответ 2

Я предполагаю, что вы используете Unix/Linux, но вы действительно не говорите. У меня нет прямых советов по вашей проблеме. Поэтому я не ожидаю, что буду "правильным" ответом на этот вопрос. Но здесь есть что изучать.

Во-первых, если ваши демоны рушится, вы должны это исправить. Только программы с ошибками должны быть повреждены. Возможно, вы должны запустить их под отладчиком и посмотреть, что происходит, когда они разбиваются (если это возможно). У вас есть отслеживание трассировки в этих процессах? Если нет, добавьте их. Это может помочь диагностировать ваш сбой.

Во-вторых, ваши демоны, предоставляющие услуги (открытие труб и ожидание запросов), или они выполняют периодическую очистку? Если они являются периодическими процессами очистки, вы должны использовать cron, чтобы запускать их периодически, а затем запускать их в бесконечном цикле. Процессы Cron должны быть предпочтительнее процессов демона. Точно так же, если они являются службами, открывающими порты и запросы на обслуживание, считаете ли вы, что они работают с INETD? Опять же, один демон (inetd) должен быть предпочтительнее группы процессов демона.

В-третьих, сохранение PID в файле не очень эффективно, как вы обнаружили. Возможно, общий IPC, как семафор, будет работать лучше. Однако у меня нет никаких подробностей.

В-четвертых, иногда мне нужно, чтобы материал запускался в контексте веб-сайта. Я использую процесс cron, который вызывает wget с URL-адресом обслуживания. Вы устанавливаете специальный файл cookie и включаете информацию о файлах cookie в командной строке wget. Если специальный файл cookie не существует, верните 403, а не выполните процесс обслуживания. Другим преимуществом здесь является вход в базу данных и другие проблемы, связанные с окружающей средой, которые можно избежать, поскольку код, обслуживающий обычные веб-страницы, обслуживает процесс обслуживания.

Надеюсь, что это даст вам идеи. Я думаю, что избегать демонов, если вы можете, это лучшее место для начала. Если вы можете запустить свой python в mod_wsgi, который сохранит вам поддержку нескольких "сред". Отладка процесса, который терпит неудачу после запуска в течение нескольких дней, является просто жестокой.

Ответ 3

Вы должны рассматривать процессы Python как способные запускать "навсегда", если у вас нет утечек памяти в вашей программе, интерпретатора Python или любых библиотек/модулей Python, которые вы используете. (Даже если вы сталкиваетесь с утечками памяти, вы можете работать вечно, если у вас есть достаточное пространство подкачки на 64-битной машине. Десятилетия, если не столетия, должны быть выполнимыми. У меня были процессы Python, два года на ограниченном оборудовании - до того, как аппаратное обеспечение необходимо было переместить.)

Обеспечение перезапуска программ, когда они умирают, было очень простым, когда использовались дистрибутивы Linux SysV-style init - вы просто добавляете новая строка с /etc/inittab и init(8) будет запускать вашу программу при загрузке и повторно запускать ее, если она умрет. (Я не знаю механизма для повторения этой функции с помощью новой upstart init -replacement, которую используют многие дистрибутивы в эти дни. я не говорю, что это невозможно, я просто не знаю, как это сделать.)

Но даже механизм init(8) прошедших лет был не таким гибким, как хотелось бы некоторым. Пакет daemontools от DJB является одним из примеров средств контроля и контроля процесса, призванных удерживать демонов навсегда. Пакет Linux-HA предоставляет другой аналогичный инструмент, хотя он может обеспечить слишком много "лишних" функциональных возможностей для оправдания этой задачи. monit - еще один вариант.