ctrl+c關閉多線程python程序


項目中經常需要用到多線程,如果一個python程序用了多線程,當子線程沒有結束時,用ctrl+c是關閉不了主線程的,這時候就只能用kill命令殺掉,這樣會很麻煩。

所以探討了下怎么ctrl+C關閉多線程python程序,也在網上查了很多別人的做法,自己做了很多實驗,嘗試了很多種方法,總結得出一個能用的方法就是,把子線程setDeamon(True),通過isAlive方法實現join的功能。

代碼:

#encoding=utf-8
__author__ = 'kevinlu1010@qq.com'
import threading
from time import sleep
def f():
        sleep(100)
p=threading.Thread(target=f)
p.setDaemon(True)
p.start()
# p.join()
while 1:
    if not p.isAlive():
        break
    sleep(1)
print 'done'

當子線程很多的時候,可以用這個函數

def threads_join(threads):
    '''
    令主線程阻塞,等待子線程執行完才繼續,使用這個方法比使用join的好處是,可以ctrl+c kill掉進程
    '''
    for t in threads:
        while 1:
            if t.isAlive():
                sleep(10)
            else:
                break

這種做法的壞處就是令主線程阻塞,直到子線程執行完這個功能的實現太麻煩了,原本用join來實現就好方便很多

 

下面是研究的過程中的嘗試,但是全部都實現不了ctrl+C關閉的功能

原始的多線程程序

def f():
    sleep(100)
p=threading.Thread(target=f)
p.start()
p.join()

print 'done'

這是最原始的一個多線程程序。

嘗試一:設置線程為守護線程,即加入

p.setDaemon(True)

但是ctrl+c,程序沒反應,跟沒加是一樣的

嘗試二:使用信號,因為ctrl c的時候系統會向程序發送sigint信號,所以我們可以令程序捕獲這個信號,並調用os的kill方法殺死自己

import signal
import os
import threading
from time import sleep
def f(a,b):
    print 'kill me'
    os.kill(os.getpid(),signal.SIGKILL)

def tf():
    sleep(20)

signal.signal(signal.SIGINT,f)
p=threading.Thread(target=tf)
p.start()
p.join()

print 'done'

程序運行后,我立刻按ctrl c ,主線程會等子線程sleep20后,才會print 'kill me',證明主線程在等待子線程執行的時候,即join的時候,是捕獲不了系統發來的信號的,要等子線程執行完畢,才能捕獲。所以這個方法還是不行。

嘗試三,用一個標志來讓子線程自己結束自己的運行

is_exit=0
def f(a,b):
    global is_exit
    is_exit=1
    print 'kill me'
    os.kill(os.getpid(),signal.SIGKILL)

def tf():
    while not is_exit:
        sleep(20)

signal.signal(signal.SIGINT,f)
p=threading.Thread(target=tf)
p.start()
while 1:
    sleep(10)

print 'done'

這里加入一個標志is_exit用來標志子線程是否繼續執行,然后加入信號,當捕獲關閉信號時,把is_exit改為1,令到子線程自己結束,由於主線程在join的狀態下是接受不了信號的,所以這里讓主線程處於一直等待的狀態。

這個做法是能做到ctrl c關閉子線程的,缺點就是子線程需要做完一個循環才能結束,同時主線程沒有了join的功能,適用於主線程在給子線程發放任務后就不需要做任何操作的情形。

 

所以總的來說,ctrl c不能關閉多線程的程序的主要原因是使用了join方法,一旦用了join,主線程就會一直處於阻塞狀態,不接受任何外界的聯系。但是join方法在實際的業務中是經常需要用到的,我查了很久也沒有查到可以替代join的,同時可以被ctrl c的方法。上面第一個程序用到的使用alive方法來實現join的功能的做法算是一個不太好,但又不能不使用它的解決方案了,希望后面能找到更好的實現join功能的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM