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

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

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)

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

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


вы, вероятно, хотите ответ "как вызвать внешнюю команду в 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. Чтобы дать вам представление о том, как начать, поместите что-то вроде этого в функцию, которая выполняет вилку (функция должна взять список или кортеж "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)