python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
目录
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() print('==主开始') # 1.在window环境下,开启进程必须__name=='__main__'下面 # 原因:这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。 # 2.p.start() # 只是向操作系统发出一个开辟子进程的信号,然后就执行下一行了,这个信号操作系统接收到之后,会从内存中开辟子进程空间,然后再将主进程所有数据copy加载到子进程,然后再调用CPU去执行. # 3.开辟子进程开销是很大的,所以永远会先执行主进程的代码
-
开启进程的第二种方式
from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super().__init__() self.name = name def run(self): print(f'{self.name} is running') time.sleep(2) print(f'{self.name} is gone') if __name__ == '__main__': p = MyProcess('张三') p.start() print('===主')
-
简单应用
from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(1) print(f'{name} is gone') def task1(name): print(f'{name} is running') time.sleep(2) print(f'{name} is gone') def task2(name): print(f'{name} is running') time.sleep(3) print(f'{name} is gone') if __name__ == '__main__': # 一个进程串行的执行三个任务 start_time = time.time() task('张三') task1('李四') task2('王五') print(f'结束时间{time.time() - start_time}') # 三个进程 并发或者并行的执行三个任务 start_time = time.time() p1 = Process(target=task, args=('李四',)) # 创建一个进程对象 p2 = Process(target=task1, args=('王五',)) # 创建一个进程对象 p1.start() p2.start() task2('张三') print(f'结束时间{time.time()-start_time}')
2. 进程PID
-
pid是进程在内存中的唯一标识
-
pid的获取:
命令行获取所有的进程的pid:tasklist;命令行获取某个进程的pid:tasklist|findstr python
代码级别获取一个进程的pid
import os print(os.getpid())
获取父进程(主进程)的pid
import os print(f'子进程:{os.getpid()}') print(f'主(父)进程:{os.getppid(())}')
-
验证进程之间的空间隔离
from multiprocessing import Process import time name = '张三' def task(): global name name = '李四' print(f'子进程{name}') if __name__ == '__main__': p = Process(target=task) # 创建一个进程对象 p.start() # print('==主开始') time.sleep(3) print(f'主:{name}') # 不能共享内存的数据
3. 进程对象join方法
-
join让主进程等待子进程结束后,再执行主进程(lock,队列)
-
示例一:简单使用
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.join() print('==主开始')
-
示例二:多个子进程使用join
# 未使用join耗时 from multiprocessing import Process import time def task(name,sec): print(f'{name}is running') time.sleep(sec) print(f'{name} is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task,args=('太阳',1)) p2 = Process(target=task,args=('月亮',2)) p3 = Process(target=task,args=('星星',3)) p1.start() p2.start() p3.start() print(f'==主{time.time()-start_time}') # 0.02 这只是主进程结束的时间,与其他进程毫无关系 # 验证1:使用join,测试多个join之后的结果以及耗时 from multiprocessing import Process import time def task(name,sec): print(f'{name}is running') time.sleep(sec) print(f'{name} is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task,args=('张三',1)) p2 = Process(target=task,args=('李四',2)) p3 = Process(target=task,args=('王五',3)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print(f'==主{time.time()-start_time}') # 结果: 张三is running 李四is running 王五is running 张三 is gone 李四 is gone 王五 is gone ==主3.2888922691345215 # 验证2:使用join,测试多个join之后的结果以及每个join之后的耗时 from multiprocessing import Process import time def task(name,sec): print(f'{name}is running') time.sleep(sec) print(f'{name} is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task,args=('张三',3)) p2 = Process(target=task,args=('李四',2)) p3 = Process(target=task,args=('王五',1)) p1.start() p2.start() p3.start() p1.join() print(f'==主1:{time.time()-start_time}') p2.join() print(f'==主2:{time.time()-start_time}') p3.join() print(f'==主3:{time.time()-start_time}') # 结果: 张三is running 李四is running 王五is running 张三 is gone 李四 is gone 王五 is gone ==主1:3.2728402614593506 ==主2:3.2728402614593506 ==主3:3.2728402614593506
-
优化使用多个join方法时的注意事项
# 优化此方法 from multiprocessing import Process import time def task(sec): print(f'is running') time.sleep(sec) print(f' is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task,args=(1,)) p2 = Process(target=task,args=(2,)) p3 = Process(target=task,args=(3,)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() # 错误示范:这样就是串行,一个执行完执行下一个 for i in range(1,4): p = Process(target=task,args=(i,)) p.start() p.join() p1 = Process(target=task,args=(1,)) p1.start() p1.join() p2 = Process(target=task,args=(2,)) p2.start() p2.join() p3 = Process(target=task,args=(3,)) p3.start() p3.join() # 正确示范: l1 = [] for i in range(1, 4): p = Process(target=task,args=(i,)) l1.append(p) p.start() for i in l1: i.join() print(f'==主{time.time()-start_time}') # join就是阻塞,主进程有join,主进程下面的代码一律不执行,直到进程执行完毕之后,再执行.
4. 进程对象其他属性
-
常见属性释义:
p.terminate() :杀死子进程
print(p.is_alive()) :判断子进程是否存活
p.name = '子进程2' :给子进程设置名称
-
代码示例:terminate/is_alive/p.name
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=('张三',),name='子进程') # 创建一个进程对象,其中的name='子进程'是给该进程设置名字为子进程 p.start() time.sleep(1) p.terminate() # 杀死子进程 *** p.join() # *** time.sleep(0.5) print(p.is_alive()) # 判断子进程是否存活 *** print(p.name) p.name = '子进程2' # 给子进程设置名称 print(p.name) print(p.pid) # 查看pid print('==主开始')
5. 守护进程
-
守护进程:子进程守护着主进程,只要主进程结束,子进程就跟着结束
-
代码示例:
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() # p.daemon = True # 一定要在子进程开启之前设置 time.sleep(1) print('===主')