一、创建多进程的类Process
multiprocess模块提供了一个创建进程的类Process,其创建进程有以下两种方法
- 创建一个peocess类实例,并指定目标任务函数
- 自定义一个类并继承Process类,重写__init__()方法和run()方法
1.验证多进程执行效率
多进程方法1(定义函数的方法):
执行代码
from multiprocessing import Process
import os
import time
# 子进程要执行的代码
def task_process(delay):
num = 0
for i in range(delay*10000000):
num += i
print(f"进程id为{os.getpid()},执行完成")
if __name__ == '__main__':
print('父进程pid为%s'% os.getpid())
t0 = time.time()
task_process(3)
task_process(3)
t1 = time.time()
print(f'顺序执行耗时:{t1 - t0}')
p0 = Process(target=task_process, args=(3,))
p1 = Process(target=task_process, args=(3,))
t2 = time.time()
p0.start(); p1.start()
p0.join(); p1.join()
t3 = time.time()
print(f"多进程执行耗时:{t3 - t2}")
执行结果:
父进程pid为12044
进程id为12044,执行完成
进程id为12044,执行完成
顺序执行耗时:2.6276705265045166
进程id为20912,执行完成
进程id为1076,执行完成
多进程执行耗时:1.5904245376586914
多进程方法2(定义类的方法):用的少
from multiprocessing import Process
import os
import time
class MyProcess(Process):
def __init__(self,delay):
self.delay = delay
print(super())
super().__init__()
def run(self):
num = 0
for i in range(self.delay*10000000):
num += i
print(f"进程id为{os.getpid()},执行完成")
if __name__ == '__main__':
print('父进程pid为%s'% os.getpid())
p0 = MyProcess(3)
p1 = MyProcess(3)
t2 = time.time()
p0.start()
p1.start()
p0.join()
p1.join()
t3 = time.time()
print(f"多进程执行耗时:{t3 - t2}")
执行结果:
父进程pid为18504
<super: <class 'MyProcess'>, <MyProcess object>>
<super: <class 'MyProcess'>, <MyProcess object>>
进程id为17484,执行完成
进程id为16772,执行完成
多进程执行耗时:1.5922276973724365
2.了解Process类的功能
-
首先看下Process类的函数源码
class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
-
参数说明:
- target:表示调用对象,一般为函数,也可以是对象
- args:表示调用对象的位置参数
- kwargs:表示调用对象的字典
- name:是进程的别名
- group:这个参数不使用,可以忽略
-
Process类提供的方法如下:
- is_alive():返回进程是否是激活的
- join([timeout]):阻塞进程,直到进程执行完成或超时或被终止
- run():代表进程执行的任务函数,在使用类的方法执行多进程时会使用,可以重写
- start():激活开启进程
- terminate():终止进程
-
Process类的属性如下:
- authkey:字节码,进程的准秘钥
- daemon:父进程终止后自动终止,且不能产生新进程,必须在start()之前设置
- exitcode():退出码,进程在运行时为None,如果为-N,就表示信号N结束
- name:获取进程的名称
- pid:进程id
二、daemon守护进程
1、不设置daemon属性示例
不加上join()阻塞
from multiprocessing import Process
import os
import time
import sys
print(sys.version)
# 子进程要执行的代码
def task_process(delay):
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程开始")
print(f"sleep {delay}s")
time.sleep(delay)
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程结束")
if __name__ == '__main__':
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程开始")
t1 = Process(target=task_process, args=(3,))
t1.start()
# t1.join()
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程结束")
执行结果:父进程会在子进程前面执行
3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)]
2021-05-18 17:46:21 父进程开始
2021-05-18 17:46:21 父进程结束
3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)]
2021-05-18 17:46:21 子进程开始
sleep 3s
2021-05-18 17:46:24 子进程结束
加上join()阻塞,父进程会等待子进程执行结束再执行
from multiprocessing import Process
import os
import time
import sys
print(sys.version)
# 子进程要执行的代码
def task_process(delay):
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程开始")
print(f"sleep {delay}s")
time.sleep(delay)
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程结束")
if __name__ == '__main__':
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程开始")
t1 = Process(target=task_process, args=(3,))
t1.start()
t1.join()
print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程结束")
执行结果:
2021-05-18 22:19:49 父进程开始
2021-05-18 22:19:49 子进程开始
sleep 3s
2021-05-18 22:19:52 子进程结束
2021-05-18 22:19:52 父进程结束
2、设置daemon属性
-
daemon() 守护进程:子进程守护着主进程,只要主进程结束,子进程跟着结束,哪怕没执行完;主进程不结束,守护进程也不会终止(会一直处于阻塞状态等待主进程结束)
-
注意:
1、将子进程设置成守护进程一定要在start()前设置,否则会报错
2、子进程跟着主进程结束,哪怕没执行完
3、主进程不结束,守护进程也不会终止(会一直处于阻塞状态等待主进程结束)
import time
from multiprocessing import Process
def task(second):
print(f'Process{second} is running')
time.sleep(second)
print(f'Process{second} is gone')
if __name__ == '__main__':
start_time = time.time()
p1 = Process(target=task, args=(1,))
p2 = Process(target=task, args=(2,))
# 设置成守护进程(必须要在start前设置,否则会报错)
p1.daemon = True
p1.start()
p2.start()
print(f'主进程runtime:{time.time() - start_time}')
执行结果:
# 输出结果:主进程执行结束,守护进程也结束,因此p1没有执行,p2进程不是守护进程,不会随着主进程的结束而结束
# 主进程runtime:0.021903276443481445
# Process2 is running
# Process2 is gone