守護進程
1、守護子進程
主進程創建守護進程
注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止
我們來看一個例子
from multiprocessing import Process import os,time,random def task(): print('%s is running' %os.getpid()) time.sleep(2) print('%s is done' %os.getpid()) #守護進程內無法再開啟子進程,否則拋出異常 # p = Process(target=time.sleep, args=(3,)) # p.start() if __name__ == '__main__': p=Process(target=task) p.daemon = True #1、必須在p.start()之前 p.start() print('主')
輸出結果如下:
主
原因是:主進程程序啟動執行到p子進程,由于子進程需要開辟內存空間,由于需要耗費時間,所以主進程會首先輸出“主”,由于主進程執行完畢,那么守護子進程p也就被干掉了,隨之主進程也就退出了
如果上面代碼修改如下,加上 p.join()這一行代碼
if __name__ == '__main__': p=Process(target=task) p.daemon = True #1、必須在p.start()之前 p.start() p.join() print('主')
那么程序會輸出如下:
14732 is running
14732 is done
主
join以前也分析過,是起到阻塞作用,子進程執行完畢,才執行主進程,所以加上join
1、執行到join,是起到阻塞作用,就會執行子進程,然后執行完畢,在執行主進程
2、也可以這樣理解,執行到join,由于主進程print(“主”)沒有執行完,所以守護進程不會被干掉,繼續執行
1、守護子進程、非守護子進程并存
在上面的例子是子進程只有一個守護進程,在主進程執行完畢,守護子進程就會被干掉 ,我們在來看一個,子進程既有守護子進程,又包含非守護子進程
from multiprocessing import Process from threading import Thread import time,os def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == '__main__': p1=Process(target=foo) p2 = Process(target=bar) p1.daemon=True p1.start() p2.start() print("main-------")
輸出如下:
main-------
456
end456
原因如下:由于p1,p2都是子進程,需要開辟內存空間,需要耗費時間,所以會優先輸出主進程“main”,由于p1是守護子進程,p2是非守護子進程,當主進程執行完畢(注意之類主進程還沒有退出,因為還有p2非守護進程),p1守護進程也就退了,但是還有一個p2非守護進程,所以p2會執行自己的代碼任務,當p2執行完畢,那么主進程也就退出了,進而整個程序就退出了
守護線程
守護子線程
無論是進程還是線程,都遵循:守護xxx會等待主xxx運行完畢后被銷毀
需要強調的是:運行完畢并非終止運行
1.對主進程來說,運行完畢指的是主進程代碼運行完畢
2.對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢
詳細解釋:
1 主進程在其代碼結束后就已經算運行完畢了(守護進程在此時就被回收),然后主進程會一直等非守護的子進程都運行完畢后回收子進程的資源(否則會產生僵尸進程),才會結束,
2 主線程在其他非守護線程運行完畢后才算運行完畢(守護線程在此時就被回收)。因為主線程的結束意味著進程的結束,進程整體的資源都將被回收,而進程必須保證非守護線程都運行完畢后才能結束。
我們先來看一個例子
from multiprocessing import Process from threading import Thread import os,time,random def task(): # t=Thread(target=time.sleep,args=(3,)) # t.start() print('%s is running' %os.getpid()) time.sleep(2) print('%s is done' %os.getpid()) if __name__ == '__main__': t=Thread(target=task) t.daemon = True t.start() print('主')
輸出如下:
13368 is running
主
原因是:
在執行到守護子線程t,由于主線程子線程通用一塊內存,所以不存在不同進程創建各自空間,所以就先輸出子進程的執行任務代碼,所以輸出print(‘%s is running' %os.getpid()),由于time.sleep(2),所以就會執行主線程“main”,然后主線程執行完畢,那么即使2秒過后,由于主線程執行完畢,那么子守護線程也就退出了,所以 print(‘%s is done' %os.getpid())就不會執行了
守護子線程非守護子進程并存
我們解析來看一個守護子線程非守護子進程并存的例子
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == '__main__': t1=Thread(target=foo) t2 = Thread(target=bar) t1.daemon=True t2.start() t1.start() print("main-------")
輸出如下:
456
123
main-------end123
end456
原因是:
t1是守護子線程,t2非守護子線程,跟主線程使用一塊內存,所以會輸出t1,t1子線程的任務代碼,所以執行456,123由于t1,t2都有睡眠時間,所以執行主線程代碼,然后對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢,所以會執行t1,t2睡眠后的任務代碼,然后程序退出。
我們會問為什么t1守護子線程,也會執行sleep后的代碼,不是說主線程代碼執行完畢,守護線程就被干掉了嗎?這里要注意是對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢,當時t2還沒執行完畢
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。