Python 如果执行Ctrl+;C当一个子进程正在执行时?

Python 如果执行Ctrl+;C当一个子进程正在执行时?,python,Python,给定以下代码: try: subprocess.Popen(ExternalProcess, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True).communicate() except KeyboardInterrupt: exit(0) 如果在执行ExternalProcess(这不是python脚本)的过程中,按下Ctrl+C命令,到底发生了什么 在这个范围内,如果我按下Ctrl+C,即使在执行ExternalPr

给定以下代码:

try:
  subprocess.Popen(ExternalProcess, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True).communicate()
except KeyboardInterrupt:
  exit(0)
如果在执行
ExternalProcess
(这不是python脚本)的过程中,按下Ctrl+C命令,到底发生了什么

在这个范围内,如果我按下Ctrl+C,即使在执行
ExternalProcess
的过程中发生,我是否可以100%确保它始终进入“除外”状态


还是取决于外部过程如何处理

据我所知,一旦您fork/exec一个进程,它就会继承父进程的。这意味着
SIGINT
(这是Ctrl+C的结果,也是
KeyboardInterrupt
的原因)将同时发送给子级和父级

以下是一个例子:

文件
a.py

import subprocess

try:
    subprocess.Popen("python b.py".split()).communicate()
except KeyboardInterrupt:
    print "a.py got ctrl-c"
文件
b.py

try:
    while True: pass
except KeyboardInterrupt:
    print "b.py got ctrl-c"
现在运行它并停止:

> python a.py
^Cb.py got ctrl-c
a.py got ctrl-c

我假设您在我的回答中使用了Unix变体。我对Windows世界没有更深入的了解

如果所有配置都正常,则
C-C
将由终端(xterm、gnome终端,…)解释。该终端将向连接到与该终端相关的tty设备的processgroup的所有进程发送一个SIGINT(请参阅
kill-l
,以了解系统的编号,通常为2)。这就是shell或shell启动的程序(以及它的所有子进程,因为进程组被继承)


但是,孩子可以自愿离开其流程组并创建一个新的流程组。守护进程通常这样做是为了避免被父程序中按下的Ctrl-C意外杀死。

这不准确。当父级退出时,
SIGINT
被发送给子级,而不是当您按下
Ctrl+C
时。没有传播。例如,如果在父级中除了KeyboardInterrupt之外,在
之后放置一个循环,则
SIGINT
不会到达子级。但我不确定进程组。@freakish我刚刚添加了
,而True:pass
a.py
的末尾,child仍在接收
SIGINT
。此外,如果在父级退出后传递了
SIGINT
,为什么要先打印
b.py的ctrl-c
?我想这可能是Python的
.communicate
的一个功能?例如,如果您执行
pr=subprocess.Popen(…)
(没有
。通信
),然后循环使用
try:time.sleep(1)除了:pass
。@freakish对我来说传播很好。如果选中
Popen.communicate()
source,则其中没有关于信号传播的内容。另请参见。@freakish:终端向同一进程组的所有成员发送信号。请参阅以下是C API的process group和Ctrl+C的一个简单示例,这可能会提供一些见解: