python實(shí)現(xiàn)守護(hù)進(jìn)程、守護(hù)線程、守護(hù)非守護(hù)并行
守護(hù)進(jìn)程
1、守護(hù)子進(jìn)程
主進(jìn)程創(chuàng)建守護(hù)進(jìn)程
- 其一:守護(hù)進(jìn)程會(huì)在主進(jìn)程代碼執(zhí)行結(jié)束后就終止
- 其二:守護(hù)進(jìn)程內(nèi)無(wú)法再開(kāi)啟子進(jìn)程,否則拋出異常:AssertionError: daemonic processes are not allowed to havechildren
注意:進(jìn)程之間是互相獨(dú)立的,主進(jìn)程代碼運(yùn)行結(jié)束,守護(hù)進(jìn)程隨即終止
我們來(lái)看一個(gè)例子
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()) #守護(hù)進(jìn)程內(nèi)無(wú)法再開(kāi)啟子進(jìn)程,否則拋出異常 # 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('主')
輸出結(jié)果如下:
主
原因是:主進(jìn)程程序啟動(dòng)執(zhí)行到p子進(jìn)程,由于子進(jìn)程需要開(kāi)辟內(nèi)存空間,由于需要耗費(fèi)時(shí)間,所以主進(jìn)程會(huì)首先輸出“主”,由于主進(jìn)程執(zhí)行完畢,那么守護(hù)子進(jìn)程p也就被干掉了,隨之主進(jìn)程也就退出了
如果上面代碼修改如下,加上 p.join()這一行代碼
if __name__ == '__main__': p=Process(target=task) p.daemon = True #1、必須在p.start()之前 p.start() p.join() print('主')
那么程序會(huì)輸出如下:
14732 is running
14732 is done
主
join以前也分析過(guò),是起到阻塞作用,子進(jìn)程執(zhí)行完畢,才執(zhí)行主進(jìn)程,所以加上join
1、執(zhí)行到j(luò)oin,是起到阻塞作用,就會(huì)執(zhí)行子進(jìn)程,然后執(zhí)行完畢,在執(zhí)行主進(jìn)程
2、也可以這樣理解,執(zhí)行到j(luò)oin,由于主進(jìn)程print(“主”)沒(méi)有執(zhí)行完,所以守護(hù)進(jìn)程不會(huì)被干掉,繼續(xù)執(zhí)行
1、守護(hù)子進(jìn)程、非守護(hù)子進(jìn)程并存
在上面的例子是子進(jìn)程只有一個(gè)守護(hù)進(jìn)程,在主進(jìn)程執(zhí)行完畢,守護(hù)子進(jìn)程就會(huì)被干掉 ,我們?cè)趤?lái)看一個(gè),子進(jìn)程既有守護(hù)子進(jìn)程,又包含非守護(hù)子進(jìn)程
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都是子進(jìn)程,需要開(kāi)辟內(nèi)存空間,需要耗費(fèi)時(shí)間,所以會(huì)優(yōu)先輸出主進(jìn)程“main”,由于p1是守護(hù)子進(jìn)程,p2是非守護(hù)子進(jìn)程,當(dāng)主進(jìn)程執(zhí)行完畢(注意之類(lèi)主進(jìn)程還沒(méi)有退出,因?yàn)檫€有p2非守護(hù)進(jìn)程),p1守護(hù)進(jìn)程也就退了,但是還有一個(gè)p2非守護(hù)進(jìn)程,所以p2會(huì)執(zhí)行自己的代碼任務(wù),當(dāng)p2執(zhí)行完畢,那么主進(jìn)程也就退出了,進(jìn)而整個(gè)程序就退出了
守護(hù)線程
守護(hù)子線程
無(wú)論是進(jìn)程還是線程,都遵循:守護(hù)xxx會(huì)等待主xxx運(yùn)行完畢后被銷(xiāo)毀
需要強(qiáng)調(diào)的是:運(yùn)行完畢并非終止運(yùn)行
1.對(duì)主進(jìn)程來(lái)說(shuō),運(yùn)行完畢指的是主進(jìn)程代碼運(yùn)行完畢
2.對(duì)主線程來(lái)說(shuō),運(yùn)行完畢指的是主線程所在的進(jìn)程內(nèi)所有非守護(hù)線程統(tǒng)統(tǒng)運(yùn)行完畢,主線程才算運(yùn)行完畢
詳細(xì)解釋?zhuān)?
1 主進(jìn)程在其代碼結(jié)束后就已經(jīng)算運(yùn)行完畢了(守護(hù)進(jìn)程在此時(shí)就被回收),然后主進(jìn)程會(huì)一直等非守護(hù)的子進(jìn)程都運(yùn)行完畢后回收子進(jìn)程的資源(否則會(huì)產(chǎn)生僵尸進(jìn)程),才會(huì)結(jié)束,
2 主線程在其他非守護(hù)線程運(yùn)行完畢后才算運(yùn)行完畢(守護(hù)線程在此時(shí)就被回收)。因?yàn)橹骶€程的結(jié)束意味著進(jìn)程的結(jié)束,進(jìn)程整體的資源都將被回收,而進(jìn)程必須保證非守護(hù)線程都運(yùn)行完畢后才能結(jié)束。
我們先來(lái)看一個(gè)例子
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
主
原因是:
在執(zhí)行到守護(hù)子線程t,由于主線程子線程通用一塊內(nèi)存,所以不存在不同進(jìn)程創(chuàng)建各自空間,所以就先輸出子進(jìn)程的執(zhí)行任務(wù)代碼,所以輸出print(‘%s is running' %os.getpid()),由于time.sleep(2),所以就會(huì)執(zhí)行主線程“main”,然后主線程執(zhí)行完畢,那么即使2秒過(guò)后,由于主線程執(zhí)行完畢,那么子守護(hù)線程也就退出了,所以 print(‘%s is done' %os.getpid())就不會(huì)執(zhí)行了
守護(hù)子線程非守護(hù)子進(jìn)程并存
我們解析來(lái)看一個(gè)守護(hù)子線程非守護(hù)子進(jìn)程并存的例子
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是守護(hù)子線程,t2非守護(hù)子線程,跟主線程使用一塊內(nèi)存,所以會(huì)輸出t1,t1子線程的任務(wù)代碼,所以執(zhí)行456,123由于t1,t2都有睡眠時(shí)間,所以執(zhí)行主線程代碼,然后對(duì)主線程來(lái)說(shuō),運(yùn)行完畢指的是主線程所在的進(jìn)程內(nèi)所有非守護(hù)線程統(tǒng)統(tǒng)運(yùn)行完畢,主線程才算運(yùn)行完畢,所以會(huì)執(zhí)行t1,t2睡眠后的任務(wù)代碼,然后程序退出。
我們會(huì)問(wèn)為什么t1守護(hù)子線程,也會(huì)執(zhí)行sleep后的代碼,不是說(shuō)主線程代碼執(zhí)行完畢,守護(hù)線程就被干掉了嗎?這里要注意是對(duì)主線程來(lái)說(shuō),運(yùn)行完畢指的是主線程所在的進(jìn)程內(nèi)所有非守護(hù)線程統(tǒng)統(tǒng)運(yùn)行完畢,主線程才算運(yùn)行完畢,當(dāng)時(shí)t2還沒(méi)執(zhí)行完畢
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python利用pyecharts實(shí)現(xiàn)數(shù)據(jù)可視化的示例代碼
Pyecharts是一個(gè)用于生成 Echarts 圖表的 Python 庫(kù),Echarts 是一個(gè)由百度開(kāi)源的數(shù)據(jù)可視化工具,它提供的圖表種類(lèi)豐富,交互性強(qiáng),兼容性好,非常適合用于數(shù)據(jù)分析結(jié)果的展示,本文將給大家介紹Python利用pyecharts實(shí)現(xiàn)數(shù)據(jù)可視化,需要的朋友可以參考下2024-09-09Python3.5集合及其常見(jiàn)運(yùn)算實(shí)例詳解
這篇文章主要介紹了Python3.5集合及其常見(jiàn)運(yùn)算,結(jié)合實(shí)例形式分析了Python3.5集合的定義、功能、交集、并集、差集等常見(jiàn)操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2019-05-05NumPy數(shù)組創(chuàng)建方法與索引訪問(wèn)詳解
這篇文章主要介紹了NumPy數(shù)組創(chuàng)建方法與索引訪問(wèn),NumPy 中的核心數(shù)據(jù)結(jié)構(gòu)是 ndarray,它代表多維數(shù)組,NumPy 提供了多種方法來(lái)創(chuàng)建 ndarray 對(duì)象,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-05-05Python實(shí)現(xiàn)清除文件夾中重復(fù)視頻
本文將利用Python中的os、hashlib、shutil模塊實(shí)現(xiàn)對(duì)文件夾中的重復(fù)視頻進(jìn)行清除,實(shí)現(xiàn)文件夾中無(wú)重復(fù)文件情況發(fā)生,需要的可以參考一下2022-05-05Python實(shí)現(xiàn)switch/case語(yǔ)句
與Java、C\C++等語(yǔ)言不同,Python中是不提供switch/case語(yǔ)句的,這一點(diǎn)讓我感覺(jué)到很奇怪。我們可以通過(guò)如下幾種方法來(lái)實(shí)現(xiàn)switch/case語(yǔ)句2021-08-08Python編程中time模塊的一些關(guān)鍵用法解析
這篇文章主要介紹了Python編程中time模塊的一些關(guān)鍵用法解析,像mktime和localtime以及gmtime這些常用方法都有講到,需要的朋友可以參考下2016-01-01python with statement 進(jìn)行文件操作指南
在Python中,with關(guān)鍵字是一個(gè)替你管理實(shí)現(xiàn)上下文協(xié)議對(duì)象的好東西。例如:file等。在file的結(jié)束,會(huì)自動(dòng)關(guān)閉該文件句柄。而這正是本文所需要的2014-08-08python使用reportlab實(shí)現(xiàn)圖片轉(zhuǎn)換成pdf的方法
這篇文章主要介紹了python使用reportlab實(shí)現(xiàn)圖片轉(zhuǎn)換成pdf的方法,涉及Python使用reportlab模塊操作圖片轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2015-05-05