2013-10-14 2 views
1

파이썬에서 시간이 많이 걸리는 스크립트를 작성했고 SIGQUIT, SIGQUIT 및 SIGINFO를 수신하는 신호 처리 모듈을 포함하여 SIGQUIT 또는 SIGINFO는 사용자가 입력하고 SIGINT (CTRL-C)를 입력하면 프로그램을 중단합니다. 내가 몇 분 안에 해킹하고 일부 외국 코드를 ​​훔쳤 기 때문에 코드가 매우 엉성함 - 걱정하지 마시고 버그를 발견하자마자 (또는 막혔습니다.)파이썬에서 외부 모듈 빠져 나오기 (신호 처리)

def setup_signals(progress_bar): 
import signal 
import sys 

def progress(*args): 
    print(progress_bar) 

def killitwithfire(*args): 
    print("[x] User interrupted with CTRL-C. Aborting.") 
    sys.exit(0) 

for sig in (signal.SIGINFO, signal.SIGQUIT): 
    signal.signal(sig, progress) 
for sig in (signal.SIGINT,): 
    signal.signal(sig, killitwithfire) 
print("Sig handlers built:\n Press Ctrl+T(BSD/OS X) or Ctrf+4(Linux) for progress.") 
print("Press CTRL-C to abort.") 

CTRL-C를 입력하면 killitwithfire() - 잘못된 참조를 유감으로 여기는 메시지가 인쇄되지만 종료되지 않습니다.

이 코드가 실행되는 코드는 try/catch/블록 안에 있습니다. 이것이 문제라면이 신호 처리 모듈에서 어떻게 빠져 나갈 수 있습니까? 문제가 아니라면 무엇입니까?

+0

죄송합니다. 들여 쓰기가 완전히 해제되었습니다. def setup_signals는 그 아래에있는 모든 코드를 포함합니다. – hellerve

답변

1

신호 처리가 주 스레드에서 수행되지 않으므로 sys.exit()을 호출하면 주 스레드를 중지하는 트릭이 수행되지 않습니다. 사실 이것을 호출하면 특수한 내부 예외 (SystemExit) 만 발생하게되어 catch되지 않으면 현재 스레드를 종료합니다. 파이썬 내부 표준 방법으로는 하나의 스레드가 종료되도록 신호를 보내는 것이므로 신호 처리 스레드를 종료해도 주 스레드가 종료되지 않습니다.

몇 가지 옵션이 있습니다.

하나는 특정 조건 (글로벌 변수 또는 threading.Condition 또는 유사)에 대한 longrunner 스레드 내부를 확인하고 "종료하십시오"라고 표시되면 루핑을 중지합니다.

운영 체제의 기능을 사용하고 스레드를 모두 사용하여 프로세스를 종료 할 수 있습니다 (예 : SIGKILL과 같은 catch 신호를 사용자 자신에게 보냄).

+0

고맙습니다. 그게 내가 바라는 대답이 아니었지만 적어도 그때 해결 방법을 제시 할 수 있습니다. – hellerve