使用KeyboardInterrupt终止子进程

时间:2016-09-14 21:32:32

标签: python windows subprocess interrupt terminate

我正在使用Python使用子进程模块调用C ++程序。由于程序需要一些时间来运行,我希望能够使用Ctrl + C终止它。我在StackOverflow上看到了一些关于这方面的问题,但没有一个解决方案对我有用。

我想要的是在KeyboardInterrupt上终止子进程。这是我的代码(类似于其他问题中的建议):

import subprocess

binary_path = '/path/to/binary'
args = 'arguments' # arbitrary

call_str = '{} {}'.format(binary_path, args)

proc = subprocess.Popen(call_str)

try:
    proc.wait()
except KeyboardInterrupt:
    proc.terminate()

但是,如果我运行它,代码将挂起,等待进程结束,并且永远不会注册KeyboardInterrupt。我也尝试了以下内容:

import subprocess
import time

binary_path = '/path/to/binary'
args = 'arguments' # arbitrary

call_str = '{} {}'.format(binary_path, args)

proc = subprocess.Popen(call_str)
time.sleep(5)
proc.terminate()

此代码段在终止程序时工作正常,因此不是发送终止的实际信号就是问题。

如何更改代码以便可以在KeyboardInterrupt上终止子进程?

我正在运行Python 2.7和Windows 7 64位。提前谢谢!

我尝试过的一些相关问题:

Python sub process Ctrl+C

Kill subprocess.call after KeyboardInterrupt

kill subprocess when python process is killed?

2 个答案:

答案 0 :(得分:3)

我找到了一种方法来做到这一点,类似于Jean-Francois对循环的回答,但没有多线程。关键是使用Popen.poll()来确定子进程是否已完成(如果仍在运行则返回None)。

import subprocess
import time

binary_path = '/path/to/binary'
args = 'arguments' # arbitrary

call_str = '{} {}'.format(binary_path, args)

proc = subprocess.Popen(call_str)

try:
    while proc.poll() is None:
        time.sleep(0.1)

except KeyboardInterrupt:
    proc.terminate()
    raise

我在KeyboardInterrupt之后添加了一个额外的加注,因此除了子进程之外,Python程序也被中断了。

编辑:根据eryksun的评论更改传递给time.sleep(0.1)以减少CPU消耗。

答案 1 :(得分:2)

我在Windows上的丑陋但成功的尝试:

import subprocess
import threading

import time

binary_path = 'notepad'
args = 'foo.txt' # arbitrary

proc = None
done = False

def s():
    call_str = '{} {}'.format(binary_path, args)
    global done
    global proc
    proc = subprocess.Popen(call_str,stdout=subprocess.PIPE)
    proc.wait()
    done = True


t = threading.Thread(target=s)
t.start()


try:
    while not done:
        time.sleep(0.1)

except KeyboardInterrupt:
    print("terminated")
    proc.terminate()

创建子进程运行的线程。导出proc变量。

然后在非活动循环中永远等待。按下CTRL + C时,将触发异常。进程间通信(例如:proc.wait())与CTRL + C处理冲突。在线程中运行时,没有这样的问题。

注意:我曾尝试使用threading.lock()来避免此时间循环,但偶然发现了同一个CTRL + C忽略。