2009-12-06 2 views
12

몇 가지 비슷한 질문이 있지만 필요한 답변을 제공하는 것은 없습니다.메인 스레드의 스레드에서 처리되지 않은 예외를 발생시키지 않습니까?

threading.Thread을 통해 스레드를 생성 한 다음 처리되지 않은 예외가 발생하면 해당 스레드가 종료됩니다. 스택 트레이스에서 예외 세부 사항의 기본 인쇄를 유지하고 전체 프로세스를 종료하고 싶습니다.

스레드의 모든 예외를 catch하고 주 스레드 개체에서 스레드를 다시 시도하거나 가능한 경우 기본 예외 처리를 수동으로 수행 한 다음 메인에 SystemExit을 발생시킬 수 있다고 생각했습니다. 실.

이 문제를 해결하는 가장 좋은 방법은 무엇입니까?

답변

15

나는 대략 Re-throwing exceptions in Python이라고 썼다.

try: 
    self.result = self.do_something_dangerous() 
except Exception, e: 
    import sys 
    self.exc_info = sys.exc_info() 

을하고 주 스레드에서이 수행합니다 : 당신의 작업자 스레드에

이 할 (파이썬 2.X를, 파이썬 3.x의 버전은 아래 참조)

if self.exc_info: 
    raise self.exc_info[1], None, self.exc_info[2] 
return self.result 

을 예외는 작업자 스레드에서 발생한 것처럼 주 스레드에 표시됩니다.

파이썬 3.x를 :

try: 
    self.result = self.do_something_dangerous() 
except Exception as e: 
    import sys 
    self.exc_info = sys.exc_info() 

하고 주 스레드에서가 :

if self.exc_info: 
    raise self.exc_info[1].with_traceback(self.exc_info[2]) 
return self.result 
+0

메인 스레드에'thrdobj.exc_info'를 던지지 말고, 다시 올릴 때 예외 유형을 버리는 이유는 무엇입니까? –

+0

3arg raise 문을 읽어야했습니다. 하지만 '자기'에 관한 질문은 여전히 ​​유효합니다. 좋은 답변을 주셔서 감사합니다. 나는 그것을 시험해 보겠습니다. –

+0

자기에 대한 당신의 질문이 무엇인지 모르겠습니다. 이 코드는 작업자 스레드로 작업을 연기하는 데 사용되는 개체에서 가져온 것이므로 동일한 개체가 작업자와 주 스레드의 코드를 실행합니다. –

9

보조 스레드가 안정적으로 메인 스레드에 올릴 수있는 유일한 예외가 KeyboardInterrupt 경우 : 방법 보조 스레드는 함수 thread.interrupt_main()을 호출하여 수행합니다. 제기 된 예외 객체와 함께 추가 정보 (예외의 이유에 대한)를 연결할 수있는 방법이 없습니다. 후자는 항상 단지 KeyboardInterrupt입니다. 따라서 다른 곳에 정보를 숨겨야합니다. 보조 인스턴스가 sys.exc_info()을 통해 얻을 수있는 결과가 포함될 수 있으며 기타 유용한 정보가 포함될 수 있습니다. Queue.Queue

메인 스레드는 그 여분의 정보를 복구해야합니다. 키보드 인터럽트가 실제로 컨트롤 C를 치는 사용자 때문인 경우 큐가 비어 있다는 것을 고려하면 get_nowait을 사용하고 준비가되어 있어야합니다 예를 들어 Queue.Empty 예외를 처리하려면 원하는대로 형식을 지정하고 종료하십시오 (모든 보조 스레드가 daemon이면 주 스레드가 종료 될 때 전체 프로세스가 종료됩니다).

+0

스레딩 문서 링크 업데이트 : https://docs.python.org/3.6/library/_thread.html?highlight=interrupt_main#_thread.interrupt_main – user2682863