Python multi-process daemon and multi-threaded daemon

Python multi-process daemon

Those of us who don't understand the torment of love, hatred, and hatred, always think that the death of love is just an ancient rumor.

1. Only one process exists, and the process is a daemon child process:
at this time, the child process is guarding the main process, as long as the main process ends, the child process ends

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

Let's put p.daemon = True before p.start and take a look:

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("主进程")

主进程

We can see that after the main process is executed, the child process is not executed (even one sentence, because the time is too late).
Let's postpone the end time of the main process to see:

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
主进程

Then the program successfully executed the first code of the child process.

2. There are not only daemons in the process, but also non-daemons:

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

We can see that the child process p2 is not executed after the main process is executed (it was said that the time is too late), but why p1 and p3 are still executed?
The reason is as follows: Because p1 and p3 are both child processes, it needs to open up memory space and takes time, so the main process will be output first, because p2 is a daemon child process, p1 and p3 are non-daemon child processes, when the main process is executed (note the main The process has not exited, because there are p1 and p3 non-daemon processes), the p2 daemon process is gone, but there are p1 and p3 non-daemon processes, so p1 and p3 will execute their own code tasks, when p1 and p3 execute After that, the main process exits, and the entire program exits.

Let's postpone the end time of the main process before continuing to see:

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

The program successfully executes the first code of the child process p2, and then after the code of the main process ends, p2 also ends. Waiting for the end of the two non-daemon child processes, p1 and p3, the process is considered as a complete end.

Python multi-threaded daemon

Multi-threaded daemons are written in the same way as multi-processes, they are all put before start.
Because the thread starts very very fast (faster than the main thread, here is an example for everyone to see:)

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
主线程

We can see the main thread that executes the content of the thread first, and then executes it.
Closer to home, the daemon thread also lets the child thread end when the main thread ends, and I will explain it to you below.

1. Only one thread exists, and this thread is a daemon child thread:

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
主线程

We can see that when the main thread ends, because the child thread is still waiting for sleep, there is enough time for the main thread to execute, and then the main process finishes-the program ends and the child thread terminates.
Note here: t.setDaemon(True) and t.daemon = True are both written for daemon threads (both can be used)

2. There are not only daemon threads but also non-daemon threads in threads:

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

From the results, we can see that after executing the program, the three child threads t1, t2, and t3 execute the first sentence of print first, and then execute the main thread while waiting for sleep. Because t1 is a daemon process, with the end of the main thread code, t1 sub-threads will end, and t2 and t3 are non-daemon threads. Although the code of the main thread is executed here and after the execution of the main thread, but for the main thread, the completion of execution means It is that all non-daemon threads in the process where the main thread is running are completed, and the main thread is considered to have finished running, so the code after sleep at t2 and t3 will be executed.

Summary: When does the main thread end? (Not print ("main thread") this code ends, but the entire thread) ends
after the daemon thread, non-daemon child threads, and (the code of the main thread) ends.

I hope this article can help you, and I feel that a well-written one can give the author some encouragement~ Your support is my motivation to move forward!

Guess you like

Origin blog.csdn.net/m0_50481455/article/details/113749775