前言:
今天為大家帶來的內容是Python:用Ctrl+C解決終止多線程程序的問題!文章中的代碼具有不錯的參考意義,希望在此能夠幫助到各位!(多數代碼用圖片的方式呈現出來,方便各位觀看與收藏)
出發點:
前段時間,花了一天時間用python為服務寫了個壓力測試。很簡單,多線程向服務器發請求。但寫完之后發現如果中途想停下來,按Ctrl+C達不到效果,自然想到要用信號處理函數捕捉信號,使線程都停下來,問題解決的方法請往下看:
代碼如下:


在這里提示一句:上面是一個模擬程序,并不真正向服務發送請求。
而代之以在一千萬以內,每個線程每隔并發數個(cc個)打印一個整數。很明顯,當所有線程都完成自己的任務后,進程會正常退出。但如果我們中途想退出(試想一個壓力測試程序,在中途已經發現了問題,需要停止測試),該腫么辦?
你當然可以用ps查找到進程號,然后kill -9殺掉,但這樣太繁瑣了,捕捉Ctrl+C是最自然的想法。上面示例程序中已經捕捉了這個信號,并修改全局變量is_exit,線程中會檢測這個變量,及時退出。
但事實上這個程序并不work,當你按下Ctrl+C時,程序照常運行,并無任何響應。網上搜了一些資料,明白是python的子線程如果不是daemon的話,主線程是不能響應任何中斷的。但設為daemon后主線程會隨之退出,接著整個進程很快就退出了,所以還需要在主線程中檢測各個子線程的狀態,直到所有子線程退出后自己才退出,因此上例29行之后的代碼可以修改為:
代碼如下:

重新試一下,問題依然沒有解決,進程還是沒有響應Ctrl+C,這是因為join()函數同樣會waiting在一個鎖上,使主線程無法捕獲信號。因此繼續修改,調用線程的isAlive()函數判斷線程是否完成:
代碼如下:
while 1: alive = False for i in range(cc): alive = alive or threads[i].isAlive() if not alive: break
注意:這樣修改后,程序完全按照預想運行了:可以順利的打印每個線程應該打印的所有數字,也可以中途用Ctrl+C終結整個進程。
完整的代碼如下:

提示:圖一,二,三中的代碼都是一起的!


其實,如果用python寫一個服務,也需要這樣,因為負責服務的那個線程是永遠在那里接收請求的,不會退出,而如果你想用Ctrl+C殺死整個服務,跟上面的壓力測試程序是一個道理。總結一下,python多線程中要響應Ctrl+C的信號以殺死整個進程,需要:
1.把所有子線程設為Daemon;
2.使用isAlive()函數判斷所有子線程是否完成,而不是在主線程中用join()函數等待完成;
3.寫一個響應Ctrl+C信號的函數,修改全局變量,使得各子線程能夠檢測到,并正常退出。
以上就是本文的全部內容啦!
小編在這里說句:我是一名python開發工程師,最近翻了以前的筆記,總結了工作這么久的經驗,共整理了一套最新的python系統學習教程,包括從基礎的python腳本到web開發、爬蟲、數據分析、數據可視化、機器學習,面試寶典,面試寶典,面試寶典。想要這些資料的可以關注小編,并在后臺私信小編:“07”即可領取