Terminating a subprocess with KeyboardInterrupt
<p>I'm using Python to call a C++ program using the subprocess module. Since the program takes some time to run, I'd like to be able to terminate it using Ctrl+C. I've seen a few questions regarding this on StackOverflow but none of the solutions seem to work for me.</p>

<p>What I would like is for the subprocess to be terminated on KeyboardInterrupt. This is the code that I have (similar to suggestions in other questions):</p>

<pre><code>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()
</code></pre>

<p>However, if I run this, the code is hung up waiting for the process to end and never registers the KeyboardInterrupt. I have tried the following as well:</p>

<pre><code>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()
</code></pre>

<p>This code snippet works fine at terminating the program, so it's not the actual signal that's being sent to terminate that is the problem.</p>

<p>How can I change the code so that the subprocess can be terminated on KeyboardInterrupt?</p>

<p>I'm running Python 2.7 and Windows 7 64-bit. Thanks in advance!</p>

<p>Some related questions that I tried:</p>

<p><a href="http://stackoverflow.com/questions/19807134/python-sub-process-ctrlc">Python sub process Ctrl+C</a></p>

<p><a href="http://stackoverflow.com/questions/33496416/kill-subprocess-call-after-keyboardinterrupt">Kill subprocess.call after KeyboardInterrupt</a></p>

<p><a href="http://stackoverflow.com/questions/1603658/kill-subprocess-when-python-process-is-killed">kill subprocess when python process is killed?</a></p>

<p>I figured out a way to do this, similar to Jean-Francois's answer with the loop but without the multiple threads. The key is to use Popen.poll() to determine if the subprocess has finished (will return None if still running). </p>

<pre><code>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
</code></pre>

<p>I added an additional raise after KeyboardInterrupt so the Python program is also interrupted in addition to the subprocess. </p>

<p>EDIT: Changed pass to time.sleep(0.1) as per eryksun's comment to reduce CPU consumption.</p>

python windows subprocess interrupt terminate