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(“主线程”)这段代码结束,是整个的线程)
在守护线程、非守护子线程以及主线程(的代码)结束之后结束。

希望本篇文章能给你们带来帮助,觉得写的不错的可以给作者一些鼓励~您的支持就是我不断前行的动力!

猜你喜欢

转载自blog.csdn.net/m0_50481455/article/details/113749775