Как запустить процесс демона из Python на Windows?

Может ли мой скрипт на python создать процесс, который будет работать бесконечно?

Я не слишком знаком ни с питоном, ни с порождающими дэймонами, поэтому придумаю это:

si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.CREATE_NEW_CONSOLE
subprocess.Popen(executable, close_fds = True, startupinfo = si)

Процесс продолжает выполняться после python.exe, но закрывается, как только я закрываю окно cmd.

3 ответа

Решение

Используя ответ, Джанн Карила указал, что это то, как вы можете запустить процесс, который не умирает, когда умирает его родитель, нет необходимости использовать win32process модуль.

DETACHED_PROCESS = 8
subprocess.Popen(executable, creationflags=DETACHED_PROCESS, close_fds=True)

DETACHED_PROCESS является флагом создания процесса, который передается в базовую функцию CreateProcess.

Этот вопрос был задан 3 года назад, и хотя основные детали ответа не изменились, учитывая его распространенность в поисках "Демон Windows Python", я подумал, что было бы полезно добавить некоторые обсуждения для будущих пользователей Google.

На самом деле есть две части вопроса:

  1. Может ли скрипт Python создать независимый процесс, который будет работать бесконечно?
  2. Может ли скрипт Python действовать как демон Unix в системе Windows?

Ответ на первый однозначный да; как уже указывалось; с помощью subprocess.Popen с creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ключевое слово будет достаточно:

import subprocess

independent_process = subprocess.Popen(
    'python /path/to/file.py',
    creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)

Обратите внимание, что, по крайней мере, по моему опыту, CREATE_NEW_CONSOLE здесь не нужно

При этом поведение этой стратегии не совсем то, что вы ожидаете от демона Unix. Что представляет собой хорошо себя ведущий демон Unix, лучше объяснить в другом месте, но подведем итог:

  1. Закройте открытые дескрипторы файлов (как правило, все они, но некоторым приложениям может потребоваться защитить некоторые дескрипторы от закрытия)
  2. Измените рабочий каталог для процесса на подходящее место, чтобы предотвратить ошибки "Directory Busy"
  3. Изменить маску создания доступа к файлу (os.umask в мире питонов)
  4. Переместите приложение в фоновый режим и отключите его от процесса инициации.
  5. Полностью развод с терминала, включая перенаправление STDIN, STDOUT, а также STDERR в разные потоки (часто DEVNULL) и предотвратить повторный захват управляющего терминала
  6. Обрабатывать сигналы, в частности, SIGTERM,

Реальность ситуации такова, что Windows, как операционная система, действительно не поддерживает понятие демона: приложения, запускаемые с терминала (или в любом другом интерактивном контексте, включая запуск из Проводника и т. Д.), Будут продолжать работать с видимым окном, если только управляющее приложение (в данном примере Python) не имеет GUI без окон. Кроме того, обработка сигналов Windows крайне неадекватна, и попытки отправить сигналы независимому процессу Python (в отличие от подпроцесса, который не выдержит закрытия терминала) почти всегда приводят к немедленному завершению этого процесса Python без какой-либо очистки (нет finally: нет atexit нет __del__, так далее).

Свернуть ваше приложение в службу Windows, хотя во многих случаях это жизнеспособная альтернатива, также не совсем подходит. То же самое относится и к использованию pythonw.exe ( версия Python без окон, которая поставляется со всеми последними двоичными файлами Windows Python). В частности, им не удается улучшить ситуацию с обработкой сигналов, и они не могут легко запустить приложение из терминала и взаимодействовать с ним во время запуска (например, для доставки аргументов динамического запуска в ваш скрипт, скажем, возможно, пароля, файла). путь и т. д.), перед "демонизацией". Кроме того, службы Windows требуют установки, которая, хотя и вполне возможна для быстрого выполнения во время выполнения при первом вызове "демона", изменяет систему пользователя (реестр и т. Д.), Что было бы весьма неожиданно, если вы пришли из мир Unix.

В свете этого я бы сказал, что запуск pythonw.exe использование подпроцесса subprocess.CREATE_NEW_PROCESS_GROUP вероятно, является ближайшим аналогом Windows для процесса Python, чтобы эмулировать традиционный демон Unix. Однако, это все еще оставляет вас с дополнительной проблемой обработки сигналов и запуска связи (не говоря уже о том, чтобы сделать ваш код зависимым от платформы, что всегда расстраивает).

Тем не менее, для любого, кто столкнется с этой проблемой в будущем, я развернул библиотеку под названием daemoniker, которая объединяет как правильную демонизацию Unix, так и вышеприведенную стратегию. Он также реализует обработку сигналов (как для систем Unix, так и для систем Windows) и позволяет передавать объекты процессу "демона" с помощью pickle. Лучше всего то, что он имеет кроссплатформенный API:

from daemoniker import Daemonizer

with Daemonizer() as (is_setup, daemonizer):
    if is_setup:
        # This code is run before daemonization.
        do_things_here()

    # We need to explicitly pass resources to the daemon; other variables
    # may not be correct
    is_parent, my_arg1, my_arg2 = daemonizer(
        path_to_pid_file,
        my_arg1,
        my_arg2
    )

    if is_parent:
        # Run code in the parent after daemonization
        parent_only_code()

# We are now daemonized, and the parent just exited.
code_continues_here()

Для этого вы можете демонизировать ваш процесс Python или, если вы используете среду Windows, вы хотите запустить его как службу Windows.

Вы знаете, я люблю ненавидеть публиковать только веб-ссылки:

Но для получения дополнительной информации по вашему требованию:

Простой способ реализации службы Windows. прочитайте все комментарии, это разрешит любые сомнения

Если вы действительно хотите узнать больше

Сначала прочитайте это

что такое процесс демона или путь создания демона python

обновление: подпроцесс не является правильным способом для достижения такого рода вещи

Другие вопросы по тегам