2016-09-14 30 views
0

私はサブプロセスモジュールを使ってPythonを使ってC++プログラムを呼び出しています。プログラムの実行には時間がかかりますので、Ctrl + Cで終了することができます。私はStackOverflowでこれに関するいくつかの質問を見てきましたが、解決策のどれも私のために働くようです。KeyboardInterruptでサブプロセスを終了する

私は、サブプロセスが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ビットを実行しています。前もって感謝します!

私が試したいくつかの関連質問:Windows上

Python sub process Ctrl+C

Kill subprocess.call after KeyboardInterrupt

kill subprocess when python process is killed?

+0

あなたのメインプログラムでctrl-cシグナルを捕まえて、それを使って 'proc.terminate()'を呼び出すのはどうですか? – CoconutBandit

+0

Python 3では '_winapi.WaitForMultipleObjects([proc._handle]、False、-1)'を使うことができます。メインスレッドでwait-allフラグがfalseの場合、この待機は自動的にPythonの 'SIGINT'イベントを含みます。 2.xでは、ctypesやPyWin32を使ってゼロから実装する必要があります。 – eryksun

+0

@eryksun提案をいただきありがとうございます。同様の機能を持ち、Python 2用にインポートできるwin32eventというモジュールがありますが、 'win32event.WaitForMultipleObjects([proc._handle]、False、-1)'を試しましたが、違いはありませんでした。 – limi44

答えて

2

私はこれを行うための方法を考え出しました。これは、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の後に追加のraiseが追加され、Pythonプログラムもサブプロセスに加えて中断されました。

EDIT:eryksunのコメントに従ってCPU消費を減らすためにtime.sleep(0.1)に変更されました。

+1

'time.sleep(.1)'は中断可能です。 'pass'の代わりにそれを使うと、CPU消費量を減らすことができます。 – eryksun

1

私の醜いが、成功し試み:

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無視でつまずきました。

関連する問題