多进程模块
1. 用于创建进程,替换了threading模块(将threading中的方法名移植过来)
2. CPython下多线程是由GIL管理,导致多核模式下效率降低,GIL在进程之中的(不同的进程拥有不同的GIL),进 程就不会受到GIL的影响,多核模式下CPU密集型程序可以使用多进程
一 multiprocessing
1. 主要用于多进程管理
2. 该模块中的方法和多线程管理模块类似
3. 包含Lock等类似于线程中的类
4. 包含特殊类:Pipe,Queue进程通信相关的类(IPC)
二 Process
Process:进程类
1. Process.__init__(self, group=None, target=None, name=None, args=(), kwargs={}, daemon=None)
self:指代当前进程对象
group:预留参数
target:目标
name:进程名称
args:目标的参数(必须是元组)
kwargs:目标的参数(必须是字典)
daemon:是否是守护进程
2. terminate() 结束当前进程
import multiprocessing,time
def music(name,n):
for i in range(n):
print('listen to the music %s %s times'%(name,i+1))
time.sleep(0.5)
def movie(name,n):
for i in range(n):
print('watch movie %s %s times'%(name,i+1))
time.sleep(0.5)
if __name__ == '__main__':
p1=multiprocessing.Process(target=music,args=('凉凉',3))
p2=multiprocessing.Process(target=movie,args=('我不是药神',3))
p1.start()
p2.start()
p1.join()
p2.join()
print('end')
三 多进程模块的其他类
1. Lock:同步锁
2. Pool:进程池
3. Queue:多进程安全队列
4. Pipe:管道
四 Lock
同步和异步:
1. 同步:原子操作不被破坏,多个进程同一时间只能有一个进程可以访问临界资源(或原子操作)
2. 异步:多个进程同一只时间可以同时访问临界资源(或原子操作)
进程之间相互独立,互不干扰
# 进程同步
import multiprocessing as m,time
lock=m.Lock()
class MyList(list):
def __init__(self):
self.l=['A','B','','','']
self.index=2
def add(self,value): l
ock.acquire()
self.l[self.index]=value
time.sleep(0.001)
self.index+=1
lock.release()
def getList(self):
return self.l
mylist=MyList()
def func(char):
mylist.add(char)
if __name__ == '__main__':
p1=m.Process(target=func,args=('C',))
p2=m.Process(target=func,args=('D',))
p1.start()
p2.start()
p1.join()
p2.join()
print(mylist.getList()) # 进程间各自独立,所以子进程修改全局变量不会影响当前主进程
五 Pool
Pool:进程池
1. 进程池可以提供指定数量的进程,用于调用
1. 当有新的进程请求提交到Pool中是,如果池没满,就会创建一个新的进程
2. 如果满了,则新的进程的请求就会等待
3. 如果Pool结束,则不会创建任何进程,也不会处理任何请求
2. 进程池的方法:
1. apply(func,[args,[kwargs]]):
阻塞执行,进程池中的进程,每次只能执行一个
Python3弃用该方法
2. apply_async(func,[args,[kwargs,[callback]]])
非阻塞执行,进程池中的进程,异步执行
3. close():
关闭pool,不再接收新的任务,池中的任务继续执行
4. terminate():
结束工作进程,不再处理未完成的进程任务
5. join():
阻塞当前进程,等待子进程的退出(join必须在close或terminate之后使用)
3. 进程池批量创建进程
import multiprocessing as m,time
def work(n):
print('Hello world: %s'%n)
time.sleep(1)
if __name__ == '__main__':
pool=m.Pool(3) # 设置进程池的容量
for i in range(10):
pool.apply_async(func=work,args=(i,))
pool.close()
pool.join() # 必须调用:如果主进程执行完毕,进程池还没执行完,主进程结束,控制台不再接收打印任务
六 Queue
1. Queue:队列 进程安全队列
2. 进程之间是相互独立的,互不干扰
让进程之间可以进行通信的一种数据结构
3. 队列的创建
Queue([maxsize])
maxsize:设置队列的容量,不设置表示无限大(不限制大小)
4. 队列对象的方法:
1. put(value): 向队列中传入值 blocked参数:bool类型 timeout参数:超时时长 如果blocked为True,并且timeout为正值,如果队列已满,到达超时时间则抛出异常: Queue.Full异常;如果为blocked为False如果队列已满,直接抛出异常
2. get():从队列中读取,并删除一个元素 blocked参数:bool类型 timeout参数:超时时长 如果blocked为True,并且timeout为正值,如果队列已空,到达超时时间则抛出异常: Queue.Full异常;如果为blocked为False如果队列已空,直接抛出异常
3. get_nowait():get(False)
4. put_nowait():put(False)
5. empty(): 判断队列是否为空,该方法不可靠
6. full(): 判断队列是否满了,该方法不可靠
7. qsize(): 返回队列中的元素个数,该方法不可靠
import multiprocessing as m ,time
def putValues(q): # 向一个队列中插入数据 q:队列对象
for i in ['A','B','C']: # i:A B C
print('发送%s到queue'%i)
q.put(i)
time.sleep(1)
def getValues(q):
while True:
value=q.get()
print('从queue中获取到数据%s'%value)
if __name__ == '__main__':
queue=m.Queue() # 创建队列对象
process1=m.Process(target=putValues,args=(queue,)) # 向队列中放入数据
process2=m.Process(target=getValues,args=(queue,)) # 从队列取出数据
process1.start()
process2.start()
process1.join()
process2.terminate()
print('end')
七 Pipe
Pipe:管道
1. 用于进程之间的通信 Pipe的底层实现是队列
2. Pipe(duplex):
duplex:双向的,通过的,设置管道对象的运行模式
返回一个元组,(conn1,conn2)代表了管道的两端
duplex:True:全双工模式(conn1和conn2都可以接收也可以发送) Flase:半双工模式(conn1只负责接收,conn2只负责发送)
3. send(mesg): 管道两端的方法 mesg:消息(对象,元素) 发送消息
4. recv(): 管道两端的方法
接收消息
接收消息提前做好准备:消息接收会让处于阻塞状态,用于等待消息的到来
如果管道关闭,调用recv方法,抛出EOFError(异常终止)
import multiprocessing as m,time
def putValues(p): # p此时为管道对象
for i in ['A','B','C']:
print('发送%s到pipe' % i)
p[1].send(i)
time.sleep(1)
def getValues(p):
while 1:
value=p[0].recv()
print('从pipe中获取到数据%s'%value)
if __name__ == '__main__':
# 创建管道对象 pipe=m.Pipe(duplex=False)
process_in=m.Process(target=putValues,args=(pipe,))
process_out=m.Process(target=getValues,args=(pipe,))
process_in.start()
process_out.start()
process_in.join()
process_out.terminate()
print('end')
八 生产者消费者模型
对于一块内存空间,有任务向该空间存储数据,同时也会有任务从该空间获取数据---生产者消费者模型(业务模型)
队列:
1. 跨进程通信队列
multiprocessing.Queue
用于进程通信
2. 队列模块
queue.Queue
不属于线程
import threading,time,queue
queue=queue.Queue()
def producer(name):# 生产者
count=1
while 1:
queue.put('第%s根香烟'%count)
print('%s 生产了第%s根香烟'%(name,count))
count+=1
time.sleep(1)
def consumer(name): # 消费者
while 1:
print('%s 拿到了 %s'%(name,queue.get()))
time.sleep(2)
if __name__ == '__main__':
l=[]
l.append(threading.Thread(target=producer,args=('老王',)))
l.append(threading.Thread(target=consumer,args=('张三',)))
l.append(threading.Thread(target=consumer,args=('李四',)))
for i in l:
i.start()