python基礎-守護進程、守護線程、守護非守護並行

守護進程

一、守護子進程

主進程建立守護進程
  其一:守護進程會在主進程代碼執行結束後就終止
  其二:守護進程內沒法再開啓子進程,不然拋出異常:AssertionError: daemonic processes are not allowed to have childrenphp

注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止python

咱們來看一個例子web

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 #一、必須在p.start()以前
    p.start()
    print('主')

輸出結果以下:app

緣由是:主進程程序啓動執行到p子進程,因爲子進程須要開闢內存空間,因爲須要耗費時間,因此主進程會首先輸出「主」,因爲主進程執行完畢,那麼守護子進程p也就被幹掉了,隨之主進程也就退出了

若是上面代碼修改以下,加上 p.join()這一行代碼dom

if __name__ == '__main__':
    p=Process(target=task)
    p.daemon = True #一、必須在p.start()以前
    p.start()
    p.join()
    print('主')

那麼程序會輸出以下:svg

14732 is running

14732 is done
主

join之前也分析過,是起到阻塞做用,子進程執行完畢,才執行主進程,因此加上join
一、執行到join,是起到阻塞做用,就會執行子進程,而後執行完畢,在執行主進程
二、也能夠這樣理解,執行到join,因爲主進程print(「主」)沒有執行完,因此守護進程不會被幹掉,繼續執行spa

一、守護子進程、非守護子進程並存

在上面的例子是子進程只有一個守護進程,在主進程執行完畢,守護子進程就會被幹掉
,咱們在來看一個,子進程既有守護子進程,又包含非守護子進程線程

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-------")

輸出以下:code

main-------
456
end456

緣由以下:因爲p1,p2都是子進程,須要開闢內存空間,須要耗費時間,因此會優先輸出主進程「main」,因爲p1是守護子進程,p2是非守護子進程,當主進程執行完畢(注意之類主進程尚未退出,由於還有p2非守護進程),p1守護進程也就退了,可是還有一個p2非守護進程,因此p2會執行本身的代碼任務,當p2執行完畢,那麼主進程也就退出了,進而整個程序就退出了xml

守護線程

守護子線程

不管是進程仍是線程,都遵循:守護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還沒執行完畢