大家看过前面文章的应该都知道python中的GIL的存在,也就是多线程的时候,同一时间只能有一个线程在CPU上运行,而且是单个CPU上运行,不管你的CPU有多少核数。如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。
Process([group [, target [, name [, args [, kwargs]]]]])
最简单的多进程方法:
from multiprocessing import Process
def fun1(name):
print('测试%s多进程' %name)
if __name__ == '__main__':
process_list = []
for i in range(5): #开启5个子进程执行fun1函数
p = Process(target=fun1,args=('Python',)) #实例化进程对象
p.start()
process_list.append(p)
for i in process_list:
p.join()
print('结束测试')
继承类Process方法:
from multiprocessing import Process
class MyProcess(Process): #继承Process类
def __init__(self,name):
super(MyProcess,self).__init__()
self.name = name
def run(self):
print('测试%s多进程' % self.name)
if __name__ == '__main__':
process_list = []
for i in range(5): #开启5个子进程执行fun1函数
p = MyProcess('Python') #实例化进程对象
p.start()
process_list.append(p)
for i in process_list:
p.join()
print('结束测试')
进程是系统独立调度核分配系统资源(CPU、内存)的基本单位,进程之间是相互独立的,每启动一个新的进程相当于把数据进行了一次克隆,子进程里的数据修改无法影响到主进程中的数据,不同子进程之间的数据也不能共享,这是多进程在使用中与多线程最明显的区别。
但是难道Python多进程中间难道就是孤立的吗?
当然不是,python也提供了多种方法实现了多进程中间的通信和数据共享(可以修改一份数据)
queue:进程之间的数据管道,实现进程通信。
有点类似派一个间谍过去,时不时的往回发送情报。
from multiprocessing import Process,Queue
def fun1(q,i):
print('子进程%s 开始put数据' %i)
q.put('我是%s 通过Queue通信' %i)
if __name__ == '__main__':
q = Queue()
process_list = []
for i in range(3):
p = Process(target=fun1,args=(q,i,)) #注意args里面要把q对象传给我们要执行的方法,这样子进程才能和主进程用Queue来通信
p.start()
process_list.append(p)
for i in process_list:
p.join()
print('主进程获取Queue数据')
print(q.get())
print(q.get())
print(q.get())
print('结束测试')
管道Pipe和Queue的作用大致差不多,也是实现进程间的通信。
有点类似量子纠缠,先设置一对纠缠粒子,把其中一个发送给子进程,然后通过量子纠缠的方式进行瞬时通信。
from multiprocessing import Process, Pipe
def fun1(conn):
print('子进程发送消息:')
conn.send('你好主进程')
print('子进程接受消息:')
print(conn.recv())
conn.close()
if __name__ == '__main__':
conn1, conn2 = Pipe() #关键点,pipe实例化生成一个双向管
p = Process(target=fun1, args=(conn2,)) #conn2传给子进程
p.start()
print('主进程接受消息:')
print(conn1.recv())
print('主进程发送消息:')
conn1.send("你好子进程")
p.join()
print('结束测试')
Queue和Pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。那么久要用到Managers。
类似定义了一个跨进程的公共变量,传入到子进程后,主进程、子进程都可以访问读写这个公共变量。
from multiprocessing import Process, Manager
def fun1(dic,lis,index):
dic[index] = 'a'
dic['2'] = 'b'
lis.append(index) # [0,1,2,3,4,0,1,2,3,4,5,6,7,8,9]
#print(l)
if __name__ == '__main__':
with Manager() as manager:
dic = manager.dict() # 注意字典的声明方式,不能直接通过{}来定义
l = manager.list(range(5)) # [0,1,2,3,4]
process_list = []
for i in range(10):
p = Process(target=fun1, args=(dic,l,i))
p.start()
process_list.append(p)
for res in process_list:
res.join()
print(dic)
print(l)
个人主页: https://weicun.gitee.io/