Python多进程
普通方式开启进程
from multiprocessing import Process import os import time def fun(i): time.sleep(3) with open('text','r') as f: count = int(f.read()) count -= 1 with open('text','w') as f: f.write(str(count)) print('这是 %s 个子进程,PID为 %s 父进程PID为 %s count:%s'%(i,os.getpid(),os.getppid(),count)) if __name__ == '__main__': p_s = [] for i in range(5): p = Process(target=fun,args=(i,)) p_s.append(p) for p in p_s: p.start()
继承的方式开启进程
from multiprocessing import Process import time class MyProcess(Process): def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) def run(self): print('开启了一个子进程...') self.fun() def fun(self): time.sleep(3) print('子进程运行了') if __name__ == '__main__': p = MyProcess() p.start()
锁
from multiprocessing import Process,Value,Lock def get_num(num,lock): for i in range(10): lock.acquire()# 获取锁 num.value -= 1 lock.release() # 释放锁 print(num.value) def put_num(num,lock): for i in range(10): lock.acquire() # 获取锁 num.value += 1 lock.release() # 释放锁 print(num.value) if __name__ == '__main__': num = Value('i',10) # Value可以在多个进程之间共享数据 lock = Lock() # 实例化一个锁 get_p = Process(target=get_num,args=(num,lock)) get_p.start() put_p = Process(target=put_num,args=(num,lock)) put_p.start() get_p.join() put_p.join() print(num.value)
信号量
from multiprocessing import Semaphore,Process import time def fun(num,lock): lock.acquire() print('%s进来了。。。'%num) time.sleep(1) lock.release() print('%s出来了....'%num) if __name__ == '__main__': lock = Semaphore(5) # 相当于实例化了一个锁,但是锁有五把钥匙 for i in range(50): p = Process(target=fun,args=(i,lock)) p.start()
from multiprocessing import Event,Process import time def signal_lamp(e): while True: if e.is_set(): # 如果当前事件状态为true那么将,状态改为false阻塞进程,模拟实现红灯亮起状态 print('红灯凉了..') e.clear()# 将event状态改为false else:# 如果当前事件状态为false那么将,状态改为true允许进程运行,模拟实现绿灯灯亮起状态 print('绿灯凉了....') e.set()#将event状态改为true time.sleep(10) def Car(i,e): e.wait() # 如果e.is_set()为false则阻塞在这一步,否则运行 print('第%s辆车过去了....'%i) if __name__ == '__main__': # Event几种方法: # event.isSet():返回event的状态值; # event.wait(): # 如果 # event.isSet() == False将阻塞进程; # event.isSet() == True 进程正常运行; # event.set(): 设置event的状态值为True,所有阻塞池的进程激活进入就绪状态, 等待操作系统调度; # event.clear():恢复event的状态值为False。 e = Event() sl = Process(target=signal_lamp,args=(e,)) sl.start() for i in range(10): p = Process(target=Car,args=(i,e,)) p.start()
生产者消费者模型Queue
from multiprocessing import Queue,Process def producer(q): for i in range(20): q.put('第 %s 个包子' % (i,)) def comsumer(q): while True: info = q.get() if not info: break print('消费:%s'%(info,)) if __name__ == '__main__': q = Queue(20) # 创建一个队列,队列内部实现了锁机制,所以在进程中共享数据是安全的 p_p = Process(target=producer,args=(q,)) p_c = Process(target=comsumer,args=(q,)) p_p.start() p_c.start() p_p.join() # 等待生产者完成 q.put(None)# 如果生产者完成了生成,则在队列中存入None如果,消费者读取到None则退出
生产者消费者模型JoinableQueue
from multiprocessing import Process,JoinableQueue def producer(q): for i in range(20): q.put('第 %s 个包子' % (i,)) q.join() # 阻塞,一直阻塞到消费者消费完所有包子(队列中记录了生产的包子个数) def comsumer(q): while True: info = q.get() print('消费:%s'%(info,)) q.task_done()# 每消费完一个包子,就会发送一个信号到队列。 if __name__ == '__main__': q = JoinableQueue(20) p_p = Process(target=producer,args=(q,)) p_c = Process(target=comsumer,args=(q,)) p_p.start() p_c.daemon = True # 将消费者进程设置为守护进程,那么当主进程的代码全部执行完毕,则会退出消费者进程 p_c.start() p_p.join() # 主进程等待生产者进程完成 ''' 这段代码的中心思想: 首先:生产者进程q.join()会等待消费者吃完所有包子之后才会结束 然后:主进程 p_p.join() 会等待生产者进程结束 最后:p_c.daemon = True 会等待主进程结束,然后结束 导致的结果:消费者吃完所有包子 -> 生产者进程结束 -> 主进程代码执行完毕 -> 消费者进程(守护进程)结束 '''
管道
from multiprocessing import Process,Pipe def producer(con): con1,con2 = con con2.close() for i in range(20): con1.send('第 %s 个包子' % (i,)) def comsumer(con): con1, con2 = con con1.close() while True: try: info = con2.recv() except EOFError: con2.close() break print('消费:%s'%(info,)) if __name__ == '__main__': # 管道内部没有实现锁机制,需要自己实现。所以管道在多进程中共享数据是不安全的 con1,con2 = Pipe() # 管道的核心,如果是con1发送,那么只能用con2接收 p_p = Process(target=producer,args=((con1,con2),)) p_c = Process(target=comsumer,args=((con1,con2),)) p_p.start() p_c.start() p_p.join() con1.close()
进程池
from multiprocessing import Pool import os import time def fun(num): return num + 1 def call_back(num): with open('a.txt','a') as f: f.write(str(num)) if __name__ == '__main__': pool = Pool(os.cpu_count()+1) # os.cpu_count() 可以计算出当前计算机的核数 # # map方法 用时:0.2000112533569336 # start = time.time() # res = pool.map(fun,range(100)) # pool.map(函数,可迭代对象) 将可迭代对象中的每一个元素传入函数计算,并且将计算结果返回 res得到一个列表 # pool.close() # 想要主进程等待进程池中的任务全部完成。首先得关闭进程池,使新任务无法在放入进程池。之后在使用pool.join()来使主进程阻塞等待 # pool.join() # print(res) # print(time.time()-start) # #apply(同步)方法,跟没开多进程一样,一个一个执行 用时 0.15600895881652832 # start = time.time() # for i in range(100): # res = pool.apply(func=fun,args=(i,)) # pool.apply(func=函数,args=(参数,)) 可以得到函数的返回值 # print(res) # print(time.time()-start) # apply(异步)方法 用时 0.08100461959838867 # pool.apply(func=函数,args=(参数,),callback=回调函数) # 使用 res.get()可以得到函数的返回值。 # 回调函数接收一个参数,参数就是func的返回值,自动传参。(回调函数由主进程调用) # #回调函数的练习 # start = time.time() # res_l = [] # for i in range(100): # res = pool.apply_async(func=fun,args=(i,),callback=call_back) # res_l.append(res) # pool.close() # pool.join() # print(time.time()-start)