天天看點

python多程序之守護程序與多線程之守護程序python多程序之守護程序python多線程之守護程序

python多程序之守護程序

不懂愛恨情仇煎熬的我們,總以為殉情隻是古老的傳言。

1.僅有一個程序存在,且該程序為守護子程序:

此時子程序守護着主程序,隻要主程序結束,子程序就跟着結束

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is gone")

if __name__ == "__main__":
    p = Process(target=task,args=("常辛",))  # 建立一個程序對象

    p.start()

    p.daemon = True  # 一定要在子程序開啟之前設定

    print("主程序")

這裡設定在了子程序開始之前,是以執行結果報錯:
    assert self._popen is None, 'process has already started'
AssertionError: process has already started
常辛 is running
常辛 is gone
           

我們将p.daemon = True放到p.start之前再來看看:

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is gone")

if __name__ == "__main__":
    p = Process(target=task,args=("常辛",))  # 建立一個程序對象

    p.daemon = True  # 将p子程序設定成守護程序,隻要主程序結束,守護程序馬上結束

    p.start()

    print("主程序")

主程序
           

我們可以看到執行完主程序就沒有執行子程序了(哪怕就一句,因為時間上來不及)

我們延緩下主程序的結束時間看看:

from multiprocessing import Process
import time

def task(name):
    print(f"{name} is running")
    time.sleep(2)
    print(f"{name} is gone")

if __name__ == "__main__":
    p = Process(target=task,args=("常辛",))  # 建立一個程序對象

    p.daemon = True  # 将p子程序設定成守護程序,隻要主程序結束,守護程序馬上結束

    p.start()

    time.sleep(1)

    print("主程序")

常辛 is running
主程序
           

則程式成功執行了子程序的第一句代碼。

2.程序中不僅有守護程序存在,還有非守護程序:

from multiprocessing import Process
import time

def task():
    print(123)
    time.sleep(1)
    print(f"end123")

def task1():
    print(456)
    time.sleep(3)
    print(f"end456")

def task2():
    print(789)
    time.sleep(5)
    print(f"end789")

if __name__ == "__main__":
    p1 = Process(target=task)  # 建立一個程序對象
    p2 = Process(target=task1)  # 建立一個程序對象
    p3 = Process(target=task2)  # 建立一個程序對象

    p2.daemon = True  # 将p2子程序設定成守護程序,隻要主程序結束,守護程序馬上結束

    p1.start()
    p2.start()
    p3.start()

    # time.sleep(1)

    print("主程序")

主程序
123
789
end123
end789
           

我們可以看到執行完主程序後沒有執行子程序p2,(上邊說過時間來不及),但是為什麼p1和p3照樣執行?

原因如下:由于p1,p3都是子程序,需要開辟記憶體空間,需要耗費時間,是以會優先輸出主程序,由于p2是守護子程序,p1和p3是非守護子程序,當主程序執行完畢(注意主程序還沒有退出,因為還有p1和p3非守護程序),p2守護程序也就沒了,但是還有p1和p3非守護程序,是以p1和p3會執行自己的代碼任務,當p1和p3執行完畢,那麼主程序也就退出了,進而整個程式就退出了。

我們延緩下主程序的結束時間再繼續看看:

from multiprocessing import Process
import time

def task():
    print(123)
    time.sleep(1)
    print(f"end123")

def task1():
    print(456)
    time.sleep(3)
    print(f"end456")

def task2():
    print(789)
    time.sleep(5)
    print(f"end789")

if __name__ == "__main__":
    p1 = Process(target=task)  # 建立一個程序對象
    p2 = Process(target=task1)  # 建立一個程序對象
    p3 = Process(target=task2)  # 建立一個程序對象

    p2.daemon = True  # 将p2子程序設定成守護程序,隻要主程序結束,守護程序馬上結束

    p1.start()
    p2.start()
    p3.start()

    time.sleep(1)

    print("主程序")

123
456
789
主程序
end123
end789
           

程式成功執行了子程序p2的第一句代碼,然後主程序的代碼結束後,p2也随之結束,等待p1和p3這兩個非守護子程序結束後,該程序才算完整結束。

python多線程之守護程序

多線程的守護程序寫法和多程序一樣,都是放到start之前。

因為線程開啟速度非常非常快(比主線程還快,這裡先舉例給大家看:)

from threading import Thread

def sayhi(name):
    print(111)
    print("%s say hello" % name)

if __name__ == "__main__":
    t = Thread(target=sayhi,args=("egon",))
    t.start()  # 線程的開啟速度比程序的要快很多

    print("主線程")

111
egon say hello
主線程
           

我們可以看到先執行完線程的内容,再執行的主線程。

言歸正傳,守護線程也是讓子線程,在主線程結束時候結束,下邊給大家進行講解。

1.僅有一個線程存在,且該線程為守護子線程:

from threading import Thread
import time

def sayhi(name):
    print(111)
    time.sleep(2)
    print("%s say hello" % name)

if __name__ == "__main__":
    t = Thread(target=sayhi,args=("egon",))

    t.setDaemon(True)  # 必須在t.start()之前設定
    # t.daemon = True
    
    t.start()  # 線程的開啟速度比程序的要快很多

    print("主線程")

111
主線程
           

我們可以看到,當主線程結束時候,因為子線程還在等待sleep,是以時間上夠主線程執行,然後主程序執行完畢——程式結束,子線程也終止了。

這裡注意:t.setDaemon(True)和t.daemon = True都為守護線程的寫法(二者皆可)

2.線程中不僅有守護線程存在,還有非守護線程:

from threading import Thread
import time


def foo():
    print(123)
    time.sleep(2)
    print("end123")

def foo1():
    print(456)
    time.sleep(1)
    print("end456")

def foo2():
    print(789)
    time.sleep(1)
    print("end789")

if __name__ == "__main__":

    t1 = Thread(target=foo)
    t2 = Thread(target=foo1)
    t3 = Thread(target=foo2)

    t1.daemon = True

    t1.start()
    t2.start()
    t3.start()

    # time.sleep(3)
    print("主線程")

123
456
789
主線程
end456
end789
           

從結果中,我們可以看出,在執行了程式後,t1、t2、t3三個子線程先執行了第一句print,然後在等待sleep時,執行了主線程。因為t1是守護程序,随着主線程代碼的結束,t1子線程随之結束,而t2和t3是非守護線程,雖然這裡以及執行完了主線程這段代碼,但是對主線程來說,運作完畢指的是主線程所在的程序内所有非守護線程統統運作完畢,主線程才算運作完畢,是以會執行t2、t3的sleep後的代碼。

總結:主線程什麼時候結束?(不是 print(“主線程”)這段代碼結束,是整個的線程)

在守護線程、非守護子線程以及主線程(的代碼)結束之後結束。

希望本篇文章能給你們帶來幫助,覺得寫的不錯的可以給作者一些鼓勵~您的支援就是我不斷前行的動力!