Как запустить фоновый процесс в Python?


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

6 206

6 ответов:

Примечание: этот ответ менее актуален, чем он был опубликован в 2009 году. Используя subprocess модуль, показанный в других ответах, теперь рекомендуется в документах

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


если вы хотите, чтобы ваш процесс начнется в фоновом режиме вы можно использовать либо system() и назовите его так же, как ваш сценарий оболочки, или вы можете spawn это:

import os
os.spawnl(os.P_DETACH, 'some_long_running_command')

(или, в качестве альтернативы, вы можете попробовать менее портативный os.P_NOWAIT флаг).

посмотреть документации.

пока jkpрешение работает, новый способ делать вещи (и то, как документация рекомендует), чтобы использовать subprocess модуль. Для простых команд его аналог, но он предлагает больше возможностей, если вы хотите сделать что-то сложное.

пример для вашего случая:

import subprocess
subprocess.Popen(["rm","-r","some.file"])

Это должно работать rm -r somefile в фоновом режиме. но будьте осторожны: subprocess.Popen() запускает процесс только в фоновом режиме, если ничего в скрипте python не зависит от вывода о выполняемой команде:

например, следующая команда не запустить в фоновом режиме:

import subprocess
ls_output=subprocess.Popen(["ls", "-a"], stdout=subprocess.PIPE)

см. документацию здесь.

кроме того, пункт разъяснения: "фон" чисто концепция оболочки: то, что вы, вероятно, хотите, чтобы породить новый процесс. Я использовал " фон " здесь, чтобы ссылаться на оболочку-фоновое поведение, но не путайте это с процессом, фактически находящимся в фон.

вы, вероятно, хотите ответ "как вызвать внешнюю команду в Python".

самый простой подход заключается в использовании

Я нашел это здесь:

В windows (win xp) родительский процесс не будет завершен до longtask.py завершила свою работу. Это не то, что вы хотите в CGI-скрипт. Проблема не специфична для Python, в сообществе PHP проблемы одинаковы.

решение состоит в том, чтобы пройти DETACHED_PROCESSФлаг Создания Процесса в базовый CreateProcess функция в win API. Если вы установили pywin32, вы можете импортировать флаг из модуль win32process, в противном случае вы должны определить его самостоятельно:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

использовать subprocess.Popen() С close_fds=True параметр, который позволит отделить порожденный подпроцесс от самого процесса Python и продолжить работу даже после выхода Python.

https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f

import os, time, sys, subprocess

if len(sys.argv) == 2:
    time.sleep(5)
    print 'track end'
    if sys.platform == 'darwin':
        subprocess.Popen(['say', 'hello'])
else:
    print 'main begin'
    subprocess.Popen(['python', os.path.realpath(__file__), '0'], close_fds=True)
    print 'main end'

вероятно, вы хотите начать исследование модуля ОС для разветвления различных потоков (открыв интерактивный сеанс и выдав справку(os)). Соответствующие функции-это fork и любой из exec. Чтобы дать вам представление о том, как начать, поместите что-то вроде этого в функцию, которая выполняет fork (функция должна принимать список или кортеж "args" в качестве аргумента, содержащего имя программы и ее параметры; вы также можете определить stdin, out и err для нового thread):

try:
    pid = os.fork()
except OSError, e:
    ## some debug output
    sys.exit(1)
if pid == 0:
    ## eventually use os.putenv(..) to set environment variables
    ## os.execv strips of args[0] for the arguments
    os.execv(args[0], args)