2014-02-09 3 views
7

С питона терминалом, я запускать некоторые команды, как в следующем, чтобы породить длительный процесс ребенка:Python многопроцессорных и независимость детей процессы

from multiprocessing.process import Process 
Process(target=LONG_RUNNING_FUNCTION).start() 

Этой команду возвращает, и я могу делать другие вещи терминал python, но все, что печатается дочерним, все еще печатается на моем сеансе терминала python.

Когда я выйти из терминала (либо с exit или CTRL +D), команды выхода он висит. Если я ударил CTRL + C Во время этого зависания дочерний процесс завершается.

Если я закрою процесс терминала python вручную (через команду posix kill), то дочерний процесс становится сиротой и продолжает работать с выводом, который предположительно будет отброшен.

Если я запускаю этот код python -c, она ждет ребенка, чтобы прекратить, и CTRL +C убивает обоих родителей и ребенка.

Какие запущенные конфигурации python убивают детей, когда родители прекращаются? В частности, если веб-сервер python-mod_wsgi-apache порождает дочерние процессы, а затем перезапускается, убиты ли дети?

[Как в стороне, какой способ отсоединения дочерних процессов от терминала? Есть ли способ более элегантно, чем следующее: Deliberately make an orphan process in python]

Update: питона подпроцессы порождали с multiprocessing.Process на веб-сервере под управлением Apache являются не убит, когда апач будет перезапущен.

ответ

12

Это не вопрос того, как вы вызываете python; это особенность модуля multiprocessing. При импорте этого модуля в родительский процесс добавляется обработчик выхода, который вызывает join() объектов Process всех детей, созданных с помощью multiprocessing.Process, прежде чем разрешить родительскому процессу выйти. Если вы собираетесь запускать дочерние процессы таким образом, нет никакого способа, не взламывая внутренние модули, чтобы избежать поведения, которое дает вам проблемы.

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

>>> from subprocess import Popen 
>>> Popen(["sleep", "100"]) 
<subprocess.Popen object at 0x10d3fedd0> 
>>> exit() 
alp:~ $ ps -opid,ppid,command | grep sleep | grep -v grep 
37979  1 sleep 100 

Есть ли конкретная причина вы используете multiprocessing вместо subprocess ? Первый не предназначен для использования для создания дочерних процессов, предназначенных для переживания родителя; он предназначен для создания дочерних процессов для работы, которые могут быть удобно распараллелены между процессорами, как способ обхода Global Interpreter Lock. (Я игнорирую распределенные возможности multiprocessing для целей этого обсуждения.) multiprocessing, таким образом, обычно используется в тех случаях, когда, если бы не было GIL, вы использовали бы потоки. (Обратите внимание, что в этом отношении API-интерфейс модуля multiprocessing тщательно моделируется после модуля threading.)

К конкретным вопросам в конце вашего сообщения: (1) Ничто из python не несет ответственности за убийство детей, когда родитель прекращается. Ребенок веб-сервера будет убит только в том случае, если родитель убивает его перед выходом (или если вся группа процессов убита). (2) Метод, на который вы ссылаетесь, выглядит так, будто он пытается реплицировать демонанизацию без знания стандартных идиом для этого. Существует множество пакетов для создания процессов демона; вы должны использовать один из них.

+0

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

+1

Различие фона/переднего плана зависит от управления заданиями в оболочке; не имеет смысла использовать эти термины в приложении для управления процессом в целом. В более общем контексте, демонанизация - это то, что процесс выполняет для себя, и использование 'subprocess.Popen' для запуска такого процесса является полностью стандартным. 'python-daemon' в порядке; он имеет громоздкий API, но это битва проверена, и последнее качество важно, так как это легко сделать неправильно. – Alp

Смежные вопросы