(Работа с python3.4 на Ubuntu 16.04)
Я пытаюсь понять, есть ли у меня поведение - это функция или что-то еще.
Я запускаю оболочку ipython и запускаю process-
subprocess.Popen("MyProcess")
После этого я хвост file-
! tail -f a_log
Затем я нажимаю кнопку управления + c, чтобы выйти из хвоста.
В результате MyProcess также останавливается.
Я вижу это, когда есть несколько процессов: все они убиты.
Также попытался перенаправить stdout и stderr на subprocess.DEVNULL, но это не помогло.
Первое, что вам нужно понять, это то, что ctrl + c вызывает отправку сигнала в группу процессов переднего плана. Второе, что вам нужно знать, это то, что группа процессов включает в себя ваш процесс Python и его открытые подпроцессы.
Например, я воссоздаю ваш эксперимент без iPython, используя 4-строчный скрипт:
import subprocess, os
pipe1 = subprocess.Popen('sleep 500', shell=True)
pipe2 = subprocess.Popen('sleep 500', shell=True)
pipe3 = subprocess.Popen('tail -f /var/log/syslog', shell=True).wait()
Как вы можете видеть, это открывает две трубки для sleep
(которые ничего не делают за 500 секунд) и один канал в tail
и следуют за /var/log/syslog
.
Теперь, с этим запуском, я собираюсь ввести ps ax -O tpgid
в другой терминал и посмотреть мои запущенные процессы, включая их идентификатор группы:
24083 24083 S pts/9 00:00:00 python3 foo.py
24084 24083 S pts/9 00:00:00 /bin/sh -c sleep 500
24085 24083 S pts/9 00:00:00 sleep 500
24086 24083 S pts/9 00:00:00 /bin/sh -c sleep 500
24087 24083 S pts/9 00:00:00 sleep 500
24088 24083 S pts/9 00:00:00 /bin/sh -c tail -f /var/log/syslog
24089 24083 S pts/9 00:00:00 tail -f /var/log/syslog
Первый столбец - это идентификатор процесса, второй - идентификатор группы, что важно.
Если я запустил kill -INT 24083
, который отправляет сигнал INT
(прерывание) в группу процессов 24083, все процессы в этой группе получают сигнал и соответственно выходят.
Это то, что происходит для вас, когда вы нажимаете ctrl + c. Группа процессов принимает сигнал, и каждый процесс, как ожидается, будет выходить за стандарт POSIX.
Я нашел способ сделать это:
import os
def myspawn():
os.setsid()
path = os.environ["PATH"] + ":/home/another/path"
env = {"PATH": path}
os.execlpe("program.sh", env)
def myFunc():
pid = os.fork()
if (pid == 0):
print("In child")
myspawn()
else:
print("in father")
return
myFunc()
Я считаю, что это то, что CTRL C делает
Popen("tail"...).wait()
, вы получите тот же результат. Если вы напишите C-программу, которая открыла два канала, и нажмете Ctrl + C, оба канала будут закрыты. Вот как работает Unix.