文章目录
- 进程Process
- 优势:
- 劣势
- 进程的创建方式(方法模式)
- 进程的创建方式(继承Process类)
- Queue实现进程间通信
- Pipe实现进程间通信
- `Manager`管理器
- 进程池(Pool)
进程Process
拥有自己独立的堆和栈,既不共享堆,也不共享栈,进程由操作系统调度;进程切换需要的资源很最大,效率低。
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。
优势:
1 可以使用计算机多核,进行任务的并行执行,提高执行效率
2 运行不受其他进程影响,创建方便
3 空间独立,数据安全
劣势
进程的创建和删除消耗的系统资源较多
进程的创建方式(方法模式)
Python的标准库提供了个模块: multiprocessing
创建进程后,使用start()
启动进程
python">#coding=utf-8
# 方法包装-多进程实现
from multiprocessing import Process
import os
from time import sleep
def func1(name):print("当前进程ID:",os.getpid())print("父进程ID:",os.getppid())print(f"Process:{name} start")sleep(3)print(f"Process:{name} end")
if __name__ =="__main__":print("当前进程ID:",os.getpid())# 创建进程p1 = Process(target=func1, args=('p1',))p2 = Process(target=func1, args=('p2',))p1.start()p2.start()
当前进程ID: 15256
当前进程ID: 4888
当前进程ID: 11388
父进程ID: 15256父进程ID: 15256
Process:p2 start
Process:p1 start
Process:p1 end
Process:p2 end
进程的创建方式(继承Process类)
和使用Thread
类创建子线程的方式非常类似,使用 Process
类创建实例化对象,其本质是调用该类的构造方法创建新进程。Process
类的构造方法格式如下:
python">def __init__(self,group=None,target=None,name=None,args=(),kwargs={})
其中,group
:该参数未进行实现,不需要传参;target
:为新建进程指定执行任务,也就是指定一个函数;name
:为新建进程设置名称;args
:为 target
参数指定的参数传递非关键字参数;kwargs
:为 target
参数指定的参数传递关键字参数。
python">from multiprocessing import Process
from time import sleep
class MyProcess(Process):def __init__(self, name):Process.__init__(self)self.name = namedef run(self):print(f"Process:{self.name} start")sleep(3)print(f"Process:{self.name} end")
if __name__ == "__main__":#创建进程p1 = MyProcess("p1")p2 = MyProcess("p2")p1.start()p2.start()
Process:p1 start
Process:p2 start
Process:p2 end
Process:p1 end
Queue实现进程间通信
前面讲解了使用 Queue
模块中的 Queue
类实现线程间通信,但要实现进程间通信,需要使用 multiprocessing
模块中的 Queue
类。
简单的理解 Queue
实现进程间通信的方式,就是使用了操作系统给开辟的一个队列空间,各个进程可以把数据放到该队列中,当然也可以从队列中把自己需要的信息取走。
python">
from multiprocessing import Process,Queue
class MyProcess(Process):def __init__(self,name,mq):Process.__init__(self)self.name = nameself.mq = mqdef run(self):print("Process:{}start".format(self.name))print('--------------',self.mq.get(),'-------------')self.mq.put(self.name)print("Process:{}end".format(self.name))
if __name__ == '__main__':# 创建进程列表t_list = []mq = Queue()mq.put('1')mq.put('2')mq.put('3')# 循环创建进程for i in range(3):t = MyProcess('p{}'.format(i),mq)t.start()t_list.append(t)# 等待进程结束for t in t_list:t.join()print(mq.get())print(mq.get())print(mq.get())
Process:p1start
Process:p2start
Process:p0start--------------
1 -------------
-------------- 2 -------------
-------------- 3 -------------
Process:p1end
Process:p0endProcess:p2end
p1
p0
p2
Pipe实现进程间通信
Pipe 直译过来的意思是“管”或“管道”,和实际生活中的管(管道)是非常类似的
Pipe方法返回(conn1, conn2)代表一个管道的两个端。
python">#coding=utf-8
import multiprocessing
from time import sleep
def func1(conn1):sub_info = "Hello!"print(f"进程1--{multiprocessing.current_process().pid}发送数据:{sub_info}")sleep(1)conn1.send(sub_info)print(f"来自进程2:{conn1.recv()}")sleep(1)
def func2(conn2):sub_info = "你好!"print(f"进程2--{multiprocessing.current_process().pid}发送数据:{sub_info}")sleep(1)conn2.send(sub_info)print(f"来自进程1:{conn2.recv()}")sleep(1)
if __name__ == '__main__':
# 创建管道conn1, conn2 = multiprocessing.Pipe()# 创建子进程process1 = multiprocessing.Process(target=func1, args= (conn1,))process2 = multiprocessing.Process(target=func2, args= (conn2,))# 启动子进程process1.start()process2.start()
进程2–15904发送数据:你好!进程1–6436发送数据:Hello!
来自进程2:你好!来自进程1:Hello!
Manager
管理器
管理器提供了一种创建共享数据的方法,从而可以在不同进程中共享。
python">
#coding=utf-8
from multiprocessing import Process,current_process
from multiprocessing import Manager
def func(name,m_list,m_dict):m_dict['name'] = 'zhangsan'm_list.append('你好')
if __name__ == "__main__":with Manager() as mgr:m_list = mgr.list()m_dict = mgr.dict()m_list.append('Hello!!')#两个进程不能直接互相使用对象,需要互相传递p1 = Process(target=func,args=('p1',m_list,m_dict))p1.start()p1.join() #等p1进程结束,主进程继续执行print(m_list)print(m_dict)
[‘Hello!!’, ‘你好’]
{‘name’: ‘zhangsan’}
进程池(Pool)
类/方法 | 功能 | 参数 |
---|---|---|
Pool(processes) | 创建进程池对象 | processes表示进程池中有多少进程 |
pool.apply_async(func,args,kwds) | 异步执行;将事件放入到进程池队列 | func 事件函数 args 以元组形式给func传参kwds 以字典形式给func传参 返回值:返回一个代表进程池事件的对象,通过返回值的get方法可以得到事件函数的返回值 |
pool.apply(func,args,kwds) | 同步执行;将事件放入到进程池队列 | func 事件函数 args 以元组形式给func传参kwds 以字典形式给func传参 |
pool.close() | 关闭进程池 | |
pool.join() | 回收进程池 | |
pool.map(func,iter) | 类似于python的map函数,将要做的事件放入进程池 | func 要执行的函数 iter 迭代对象 |
python">#coding=utf-8
from multiprocessing import Pool
import os
from time import sleep
def func1(name):print(f"当前进程的ID:{os.getpid()},{name}")sleep(2)return name
def func2(args):print(args)
if __name__ == "__main__":pool = Pool(5)pool.apply_async(func = func1,args=('z1',),callback=func2)pool.apply_async(func = func1,args=('z2',),callback=func2)pool.apply_async(func = func1,args=('z3',),callback=func2)pool.apply_async(func = func1,args=('z4',))pool.apply_async(func = func1,args=('z5',))pool.apply_async(func = func1,args=('z6',))pool.apply_async(func = func1,args=('z7',))pool.apply_async(func = func1,args=('z8',))pool.close()pool.join()
当前进程的ID:18736,z1
当前进程的ID:17316,z2
当前进程的ID:12900,z3
当前进程的ID:10120,z4
当前进程的ID:1680,z5
当前进程的ID:10120,z6
当前进程的ID:17316,z7
当前进程的ID:1680,z8
z2
z1
z3