2016-09-14 4 views
0

저는 파이썬을 사용하여 하위 프로세스 모듈을 사용하여 C++ 프로그램을 호출하고 있습니다. 프로그램을 실행하는 데 시간이 걸리기 때문에 Ctrl + C를 사용하여 프로그램을 종료 할 수 있습니다. 이 질문에 StackOverflow에 관한 몇 가지 봤지만 솔루션 중 아무 것도 나를 위해 작동하는 것.KeyboardInterrupt를 사용하여 하위 프로세스 종료

내가 좋아할 부분은 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() 

:이 (다른 질문에 제안 유사) 내가 가지고있는 코드입니다. 내가 시도했던뿐만 아니라 다음은 그게 문제입니다 종료 전송되고있는 실제 신호하지 그래서

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

파이썬 3에서는'_winapi.WaitForMultipleObjects ([proc._handle], False, -1)'를 사용할 수 있습니다. 주 스레드의 경우 wait-all 플래그가 false 인 경우이 대기는 자동으로 파이썬의'SIGINT' 이벤트를 포함합니다. 2.x에서는 ctypes 또는 PyWin32를 사용하여 이것을 처음부터 구현해야합니다. – eryksun

+0

@eryksun 제안에 감사드립니다.비슷한 기능을 갖고 파이썬 2에서 가져올 수있는 win32event라는 모듈이 있지만'win32event.WaitForMultipleObjects ([proc._handle], False, -1)'를 시도해 보았지만 큰 차이는 없었다. – limi44

답변

2

루프를 사용했지만 Jean-Francois의 대답과 유사하지만 다중 스레드가없는 방법을 찾아 냈습니다. 핵심은 Popen.poll()을 사용하여 하위 프로세스가 완료되었는지 확인하는 것입니다 (아직 실행중인 경우 없음을 반환 함).

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 다음에 추가 레이즈를 추가 했으므로 파이썬 프로그램도 하위 프로세스 외에도 중단되었습니다.

EDIT : CPU 소비를 줄이기 위해 eryksun의 설명에 따라 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 무시를 발견했습니다.