python基礎-守護程序、守護執行緒、守護非守護並行
守護程序
1、守護子程序
主程序建立守護程序
其一:守護程序會在主程序程式碼執行結束後就終止
其二:守護程序內無法再開啟子程序,否則丟擲異常:AssertionError: daemonic processes are not allowed to have children
注意:程序之間是互相獨立的,主程序程式碼執行結束,守護程序隨即終止
我們來看一個例子
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還沒執行完畢