我正在使用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()这段代码可以很好地终止程序,所以问题并不是发送给terminate的实际信号。
如何更改代码,以便可以在KeyboardInterrupt上终止子进程?
我运行的是Python 2.7和64位Windows 7。提前感谢!
我尝试了一些相关的问题:
发布于 2016-09-15 13:24:16
我想出了一种方法来做到这一点,类似于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的评论将pass更改为time.sleep(0.1),以减少CPU消耗。
发布于 2016-09-15 05:44:10
我在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 ignore。
https://stackoverflow.com/questions/39499959
复制相似问题