복붙노트

[PYTHON] 파이썬에서 스레드 내에서 호출 될 때 sys.exit ()가 종료되지 않는 이유는 무엇입니까?

PYTHON

파이썬에서 스레드 내에서 호출 될 때 sys.exit ()가 종료되지 않는 이유는 무엇입니까?

이것은 어리석은 질문 일 수 있지만 파이썬에 대한 내 가정을 테스트하고 있는데 다음 코드 스 니펫이 스레드에서 호출 될 때 종료되지 않고 메인 스레드에서 호출 될 때 종료되는 이유에 대해 혼란 스럽습니다.

import sys, time
from threading import Thread

def testexit():
    time.sleep(5)
    sys.exit()
    print "post thread exit"

t = Thread(target = testexit)
t.start()
t.join()
print "pre main exit, post thread exit"
sys.exit()
print "post main exit"

sys.exit ()에 대한 문서에서는 호출이 파이썬에서 종료되어야한다고 명시되어 있습니다. 나는이 프로그램의 출력에서 ​​"post thread exit"가 결코 출력되지 않는다는 것을 알 수있다. 그러나 메인 쓰레드는 스레드가 exit를 호출 한 후에도 계속 진행한다.

인터프리터의 개별 인스턴스가 각 스레드에 대해 작성되고 exit ()에 대한 호출이 개별 인스턴스를 종료하는 중입니까? 그렇다면 스레딩 구현이 공유 리소스에 대한 액세스를 어떻게 관리합니까? 스레드에서 프로그램을 종료하고 싶다면 (실제로 원하는 것은 아니지만 단지 이해할 수 있습니다)?

해결법

  1. ==============================

    1.sys.exit ()는 thread.exit ()와 마찬가지로 SystemExit 예외를 발생시킵니다. 따라서 sys.exit ()가 해당 스레드 내에서 예외를 발생 시키면 thread.exit ()을 호출하는 것과 동일한 효과를 가지므로 스레드 만 종료됩니다.

    sys.exit ()는 thread.exit ()와 마찬가지로 SystemExit 예외를 발생시킵니다. 따라서 sys.exit ()가 해당 스레드 내에서 예외를 발생 시키면 thread.exit ()을 호출하는 것과 동일한 효과를 가지므로 스레드 만 종료됩니다.

  2. ==============================

    2.적어도 리눅스에서는 다음과 같이 할 수 있습니다 :

    적어도 리눅스에서는 다음과 같이 할 수 있습니다 :

    os.kill(os.getpid(), signal.SIGINT)
    

    이것은 SIGINT를 KeyboardInterrupt처럼 처리 할 수있는 메인 쓰레드로 보낸다.

    BTW : Windows에서는 SIGTERM 신호 만 보낼 수 있습니다.이 신호는 Python에서 잡을 수 없습니다. (필자는 Helmut에서 제안한 os._exit 호출을 선호합니다)

  3. ==============================

    3.내가 선호하는 방법은 Erlang-ish 메시지 전달 방법이다. 약간 simlified, 나는 이것을 좋아한다 :

    내가 선호하는 방법은 Erlang-ish 메시지 전달 방법이다. 약간 simlified, 나는 이것을 좋아한다 :

    import sys, time
    import threading
    import Queue # thread-safe
    
    class CleanExit:
      pass
    
    ipq = Queue.Queue()
    
    def testexit(ipq):
      time.sleep(5)
      ipq.put(CleanExit)
      return
    
    threading.Thread(target=testexit, args=(ipq,)).start()
    while True:
      print "Working..."
      time.sleep(1)
      try:
        if ipq.get_nowait() == CleanExit:
          sys.exit()
      except Queue.Empty:
        pass
    
  4. ==============================

    4.Deestan이 설명한 방법 외에도 os._exit (밑줄을 주목하십시오)을 호출 할 수 있습니다. 그것을 사용하기 전에 그것이 정리 (__del__ 또는 이와 유사한 호출)를하지 않는다는 것을 이해했는지 확인하십시오.

    Deestan이 설명한 방법 외에도 os._exit (밑줄을 주목하십시오)을 호출 할 수 있습니다. 그것을 사용하기 전에 그것이 정리 (__del__ 또는 이와 유사한 호출)를하지 않는다는 것을 이해했는지 확인하십시오.

  5. ==============================

    5.사실 "pre main exit, post thread exit"가 인쇄되어 여러분을 괴롭 히고 있습니까?

    사실 "pre main exit, post thread exit"가 인쇄되어 여러분을 괴롭 히고 있습니까?

    아날로그에서 sys.exit (Java의 경우 System.exit)이 VM / 프로세스 / 인터프리터를 즉시 멈추게하는 다른 언어 (예 : Java)와는 달리 Python의 sys.exit은 예외, 특히 SystemExit 예외를 throw합니다.

    다음은 sys.exit에 대한 문서입니다 (단지 sys.exit .__ doc__를 출력하십시오) :

    이것은 몇 가지 결과를 낳습니다.

    마지막 것은 아마도 가장 놀랄만 한 일이며, 파이썬 코드에서 무조건 except 문을 거의 사용하지 않아야하는 또 다른 이유입니다.

  6. from https://stackoverflow.com/questions/905189/why-does-sys-exit-not-exit-when-called-inside-a-thread-in-python by cc-by-sa and MIT license