subprocess.Popen 和 ipython
subprocess.Popen and ipython
(在 Ubuntu 16.04 上使用 python3.4)
我正在尝试了解我的行为是特性还是其他。
我正在开始一个 ipython shell,并开始一个过程-
subprocess.Popen("MyProcess")
之后,我尾一个文件-
! tail -f a_log
然后,我按control+c退出尾部。
结果是MyProcess也停止了。
当有几个进程时我看到这个 运行 = 它们都被杀死了。
还尝试将 stdout 和 stderr 重定向到 subprocess.DEVNULL,但这没有帮助。
我相信这就是 CTRL C 所做的
首先要明白的是,ctrl+c导致一个signal被发送到foregrand任务的进程组。您需要知道的第二件事是进程组包括您的 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
.
现在,有了 运行ning,我将在另一个终端中输入 ps ax -O tpgid
并查看我的 运行ning 进程 ,包括它们的组 ID:
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
第一列是进程ID,第二列是组ID,很重要。
如果我运行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()
(在 Ubuntu 16.04 上使用 python3.4)
我正在尝试了解我的行为是特性还是其他。
我正在开始一个 ipython shell,并开始一个过程-
subprocess.Popen("MyProcess")
之后,我尾一个文件-
! tail -f a_log
然后,我按control+c退出尾部。
结果是MyProcess也停止了。
当有几个进程时我看到这个 运行 = 它们都被杀死了。
还尝试将 stdout 和 stderr 重定向到 subprocess.DEVNULL,但这没有帮助。
我相信这就是 CTRL C 所做的
首先要明白的是,ctrl+c导致一个signal被发送到foregrand任务的进程组。您需要知道的第二件事是进程组包括您的 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
.
现在,有了 运行ning,我将在另一个终端中输入 ps ax -O tpgid
并查看我的 运行ning 进程 ,包括它们的组 ID:
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
第一列是进程ID,第二列是组ID,很重要。
如果我运行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()