2013-01-20 1 views
3

다음 프로그램은 Ctrl+C을 무시하도록 터미널을 중단합니다. 하나의 스레드가 멈출 때마다 터미널을 다시 시작해야하기 때문에 이것은 다소 짜증이납니다.이벤트에서 대기중인 프로그램에서 키보드 인터럽트 잡기

이벤트를 기다리는 동안 KeyboardInterrupt을 잡을 방법이 있습니까?

import threading 
def main(): 
    finished_event = threading.Event() 
    startThread(finished_event) 
    finished_event.wait()#I want to stop the program here 
    print('done!') 
def startThread(evt): 
    """Start a thread that will trigger evt when it is done""" 
    #evt.set() 
if __name__ == '__main__': 
    main() 

답변

1

업데이트 : 현재 파이썬 내 우분투 시스템에서 3 개 finished_event.wait() 작품에는 (파이썬 3.2부터 시작). Ctrl + C을 사용하여 매개 변수를 중단하려면 timeout 매개 변수를 지정할 필요가 없습니다. 당신은 여기에 전체 코드 예제

CPython의 2에 timeout 매개 변수를 전달해야합니다

#!/usr/bin/env python3 
import threading 

def f(event): 
    while True: 
     pass 
    # never reached, otherwise event.set() would be here 

event = threading.Event() 
threading.Thread(target=f, args=[event], daemon=True).start() 
try: 
    print('Press Ctrl+C to exit') 
    event.wait() 
except KeyboardInterrupt: 
    print('got Ctrl+C') 

Ctrl+C 관련 bugs가있을 수 있습니다. 해당 환경에서 작동하는지 테스트하십시오.


올드 폴링 답 :

당신은 인터프리터가 메인 스레드 실행할 수 있도록 시도 할 수

: 당신은 그냥 자식 스레드가 완료 될 때까지 대기 할 경우

while not finished_event.wait(.1): # timeout in seconds 
    pass 

를 :

while thread.is_alive(): 
    thread.join(.1) 
+2

폴링없이이 작업을 수행 할 수 있습니까? – Navin

+1

잘 모르겠습니다. 폴링과 함께 작동합니까? 왜 투표가 나쁜가? 'time.sleep (large_timeout)'이'Ctrl + C '에 의해 중단되었는지 테스트 할 수 있습니다. 여전히 폴링 중이지만 곧 Ctrl + C에 반응 할 것입니다. 이벤트에 대한 응답 성이 필요한 경우에는 'finished_event.set()'에서 반응해야하는 코드를이 스레드의 또 다른 스레드에 넣어야합니다. – jfs

+1

글쎄, 나는 정말로 응답 성이 필요하지 않을 때에도 폴링을 피하는 경향이 있지만 이것이 유일한 해결책이라고 생각한다. – Navin

3

폴링을 피하려면 다음을 사용할 수 있습니다. finished_event.wait() 대신 signal 모듈의 pause() 기능을 사용하십시오. signal.pause()은 블로킹 기능이며 프로세스가 신호를 수신하면 차단 해제됩니다. 이 경우^C를 누르면 SIGINT 신호가 함수를 차단 해제합니다. 이 기능은 Windows에서 설명서에 따라 작동하지 않습니다. 나는 리눅스에서 그것을 시도했고 그것은 나를 위해 일했다.

이 SO thread에서이 솔루션을 발견했습니다.

+1

조금 늦었지만 대답이 아닌 대답을 주셔서 감사합니다 :) – Navin

+1

답을 간단하고 직접적으로 편집 할 수 있다고 생각하지만 문제를 해결했습니다. 감사합니다. –

+0

@Navin : Windows에서 작동합니까? – jfs

0

당신은 또한 다음과 같은 방식으로 Event.wait() 함수를 패치 할 수는 : 타임 아웃 인수 와 대기가() KeyboardInterrupt 인상 때문에

def InterruptableEvent(): 
    e = threading.Event() 

    def patched_wait(): 
     while not e.is_set(): 
      e._wait(3) 

    e._wait = e.wait 
    e.wait = patched_wait 
    return e 


>>> event = InterruptableEvent() 
>>> try: 
...  event.wait() 
... except KeyboardInterrupt: 
...  print "Received KeyboardInterrupt" 
... 
^CReceived KeyboardInterrupt 

이 작동합니다.

+0

아하지만 이것은 아직 수락 된 답변처럼 폴링 중입니다. ( – Navin

관련 문제