2012-02-13 9 views
5

다중 스레드 Python 프로그램에서 한 스레드가 내장 된 raw_input()을 사용하여 콘솔 입력을 요청하는 경우가 있습니다. raw_input 프롬프트에서 쉘에서^C를 입력하여 (즉, SIGINT 신호로) 프로그램을 닫을 수있게하고 싶습니다. 그러나 자식 스레드가 raw_input을 실행할 때^C를 입력하면 아무 일도 일어나지 않습니다. raw_input을 떠날 때까지 KeyboardInterrupt가 발생하지 않습니다. 다음의 프로그램, 예를 들어^C/KeyboardInterrupt가있는 자식 스레드에서 Python raw_input() 인터럽트

:

import threading 

class T(threading.Thread): 
    def run(self): 
     x = raw_input() 
     print x 

if __name__ == '__main__': 
    t = T() 
    t.start() 
    t.join() 

타이핑^C 입력이 종료 할 때까지 아무것도하지 않는다. 그러나 T().run() (즉, 단일 스레드의 경우 : 메인 스레드에서 raw_input 만 실행하면)^C는 즉시 프로그램을 닫습니다.

아마도 이것은 SIGINT가 주 스레드로 보내지기 때문입니다.이 스레드는 콘솔의 분기 된 스레드 블록을 읽는 동안 일시 중단 (GIL을 기다리는 중)됩니다. 주 스레드는 raw_input이 반환 된 후에 GIL을 잡을 때까지 시그널 핸들러를 실행하지 않습니다. (이 문제에 대해 내가 틀렸다면 수정하십시오. 파이썬의 스레딩 구현에 대한 전문가가 아닙니다.)

SIGINT를 처리하는 동안 raw_input 방식으로 stdin에서 읽는 방법이 있습니까? 주 스레드에 의해 전체 과정을 중단합니까? [내가 맥 OS X와 ​​몇 가지 다른 Linuxes에 위의 동작을 관찰했습니다.]


편집 : 나는 위의 근본적인 문제를 mischaracterized했습니다. 추가 조사에서 신호 처리를 방해하는 것은 join()에 대한 주 스레드의 호출입니다. Guido van Rossum 자신이 the underlying lock acquire in join is uninterruptible을 설명했습니다. 이것은 신호가 실제로 전체 스레드가 완료 될 때까지 연기된다는 것을 의미합니다. 따라서 이것은 실제로는 raw_input과 아무 관련이 없습니다 (배경 스레드가 차단되어 조인이 완료되지 않는다는 사실과 전혀 관련이 없습니다).

+3

단순히 스레드와 인터럽트를 결합하지 않습니다 ... [boromir.jpg] – JBernardo

답변

0

이 문제를 해결하기위한 쉬운 방법은 없습니다.

한 가지 방법은 Ctrl-C 인터럽트 가능성이 필요한 기능 부분이 주 스레드에서 실행되는 방식으로 코드를 재구성하고 해체하는 것입니다. 대기열을 사용하여 실행 요청을 보내고 마찬가지로 결과 값을 보냅니다. 메인 쓰레드를위한 하나의 입력 큐와 비 메인 쓰레드 당 하나의 출력 큐가 필요하다; 및 조정 된 주 스레드 출구. 분명히 한 번에 하나의 블로킹 함수 만이 주어진 시간에 실행되기 때문에 원하는 것이 아닐 수도 있습니다.

Here's a working example of this idea 조정 된 주 스레드 종료에 대한 세마포어를 약간 잘못 사용합니다.

3

제한 시간없이 조인을 호출하면 인터럽트가 발생하지 않지만 시간 초과와 함께 호출되면 인터럽트 가능합니다. 임의의 시간 제한을 추가하고 while 루프에 넣으십시오.

while my_thread.isAlive(): 
    my_thread.join(5.0)