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()