2009-09-28 46 views

回答

33

如果除了主線程之外的所有線程都是守護進程,最好的方法通常是thread.interrupt_main()--任何線程都可以在主線程中使用它來提升KeyboardInterrupt,這通常可以合理地從主線程中清除退出包括主線程中的終結器被調用等)。當然,如果這導致一些非守護進程線程保持整個進程活着,您需要跟進os._exit馬克建議 - 但我會看到作爲最後的手段(有點像一個kill -9;有點像kill -9; - ),因爲它非常粗暴地終止了事情(終結器未運行,包括try/finally塊,with塊,atexit函數等)。

+0

您的鏈接已經死了。 – OrangeDog 2016-06-30 16:10:14

28

簡答題:使用os._exit

朗答案與例如:

我猛拉,並略作修改一個簡單的線程例如,從a tutorial on DevShed

import threading, sys, os 

theVar = 1 

class MyThread (threading.Thread): 

    def run (self): 

     global theVar 
     print 'This is thread ' + str (theVar) + ' speaking.' 
     print 'Hello and good bye.' 
     theVar = theVar + 1 
     if theVar == 4: 
      #sys.exit(1) 
      os._exit(1) 
     print '(done)' 

for x in xrange (7): 
    MyThread().start() 

如果你保持sys.exit(1)註釋掉,腳本將第三線程打印出來後死亡。如果您使用sys.exit(1)並註釋掉os._exit(1),則第三個線程會執行而不是 print (done),並且該程序將在所有七個線程中運行。

os._exit「通常應該只在fork()」之後的子進程中使用 - 並且一個單獨的線程足夠接近您的目的。另請注意,在該手冊頁中有os._exit之後列出了幾個枚舉值,您應該更喜歡那些作爲os._exit的參數,而不是像上面示例中使用的簡單數字。

11

在某些情況下使用thread.interrupt_main()可能不起作用。經常在命令行應用程序中使用KeyboardInterrupt來退出當前命令或清理輸入行。

此外,os._exit會立即終止進程,而不會在代碼中運行任何finally塊,這可能很危險(例如,文件和連接將不會關閉)。

我找到的解決方案是在引發自定義異常的主線程中註冊一個信號處理程序。使用後臺線程來觸發信號。

import signal 
import os 
import threading 
import time 


class ExitCommand(Exception): 
    pass 


def signal_handler(signal, frame): 
    raise ExitCommand() 


def thread_job(): 
    time.sleep(5) 
    os.kill(os.getpid(), signal.SIGUSR1) 


signal.signal(signal.SIGUSR1, signal_handler) 
threading.Thread(target=thread_job).start() # thread will fire in 5 seconds 
try: 
    while True: 
     user_input = raw_input('Blocked by raw_input loop ') 
     # do something with 'user_input' 
except ExitCommand: 
    pass 
finally: 
    print('finally will still run') 

相關問題: