标签:执行流程 进程终止 生产者消费者模式 定时 代码执行 als 自定义 attribute result
一、multiprocess.process模块
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法
p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True
p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
p.name:进程的名称
p.pid:进程的pid
p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)
p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)
from multiprocessing import Process def func(name): print(‘子进程:你好,‘,name) if __name__ == ‘__main__‘: p = Process(target=func,args=(‘hsr‘,)) p.start()
from multiprocessing import Process import os def func(): print(‘子进程PID:‘,os.getpid()) if __name__ == ‘__main__‘: p = Process(target=func) p.start() print(‘父进程PID:‘,os.getpid())
from multiprocessing import Process import time def func(*args): print(‘*‘*args[0]) time.sleep(5) print(‘*‘ * args[1]) if __name__ == ‘__main__‘: p = Process(target=func,args=(10,20)) p.start() p.join() #主线程等待p终止 print("-------运行完了-------")
from multiprocessing import Process import time def func(no,*args): print(str(no)+" :"+‘*‘*args[0]) time.sleep(5) print(str(no)+" :"+‘*‘*args[1]) if __name__ == ‘__main__‘: p_li = [] for i in range(10): p_li.append(Process(target=func,args=(i,10,20))) for i in p_li: i.start() [i.join() for i in p_li] #让最后的print等子进程都结束了再执行 print(‘运行完了‘)
#自定义类 继承Process类 #必须实现run方法,run方法就是子进程执行的方法 #如果要参数,则实现自己的init方法,并在其中调用父类的init方法 from multiprocessing import Process import os class MyProcess(Process): def __init__(self,arg1): super().__init__() self.arg1 = arg1 def run(self): print("My Process:",self.pid) print(self.arg1) if __name__ == ‘__main__‘: print(os.getpid()) p1 = MyProcess(4) p1.start()
#进程间不会共享数据 from multiprocessing import Process import os def func(): global n n = 0 print(‘pid:‘+str(os.getpid())+" "+str(n)) if __name__ == ‘__main__‘: n = 100 p = Process(target=func) p.start() p.join() print(‘pid:‘+str(os.getpid())+" "+str(n))
#守护进程 from multiprocessing import Process import time def func(): while 1: time.sleep(2) print(‘Good‘) if __name__ == ‘__main__‘: p = Process(target=func) p.daemon = True #设置子进程为守护进程 p.start() i = 10 while i>0: print(‘Do something‘) time.sleep(5) i -= 1
二、进程同步
#模拟吃50个人吃5个苹果 #使用Lock对象的acquire请求锁,release释放锁 from multiprocessing import Process from multiprocessing import Lock import json def eat(no,lock): lock.acquire() with open(‘info.json‘) as f: dic = json.load(f) AppleNum = dic["Apple"] print("苹果个数:" + str(AppleNum)) if AppleNum >0: print("%d 吃了一个苹果" %no) AppleNum -= 1 dic["Apple"] = AppleNum with open(‘info.json‘,‘w‘) as f: json.dump(dic,f) else: print("%d 没有苹果吃了" %no) lock.release() if __name__ == ‘__main__‘: lock = Lock() for i in range(50): Process(target=eat, args=(i,lock)).start()
from multiprocessing import Process,Semaphore import time import random def grid(i,sem): sem.acquire() print(str(i)+‘放入了格子‘) time.sleep(random.randint(2,6)) print(str(i)+‘拿出了格子‘) sem.release() if __name__ == ‘__main__‘: sem = Semaphore(4) for i in range(20): Process(target=grid,args=(i,sem)).start()
from multiprocessing import Event if __name__ == "__main__": e = Event() # c创建一个事件 print(e.is_set()) # 查看一个事件的状态 e.set() #将事件的状态改为True e.wait() #根据e.is_set()的值决定是否阻塞 print(1235455) e.clear() #将事件的状态改为False e.wait() print(12323545555)
from multiprocessing import Event,Process import time import random def traffic_light(e): while 1: if e.is_set(): e.clear() print(‘\033[31m[-----------红灯-----------]\033[0m‘) else: e.set() print(‘\033[32m[-----------绿灯-----------]\033[0m‘) time.sleep(2) def car(e,i): if not e.is_set(): print(‘%s号车在等红灯‘ %i) e.wait() #阻塞直到状态改变 print(‘\033[0;32;40m%s号车通过\033[0m‘ %i) if __name__ == ‘__main__‘: e = Event() light = Process(target=traffic_light,args=(e,)) light.start() for i in range(20): time.sleep(random.random()) cars = Process(target=car,args=(e,i)) cars.start()
三、进程间通信
1.队列Queue
Queue([maxsize])
创建共享的进程队列。maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。底层队列使用管道和锁定实现。另外,还需要运行支持线程以便队列中的数据传输到底层管道中。
Queue的实例q具有以下方法:
q.get( [ block [ ,timeout ] ] )
返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 如果设置为False,将引发Queue.Empty异常(定义在Queue模块中)。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
q.get_nowait( )
同q.get(False)方法。
q.put(item [, block [,timeout ] ] )
将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。block控制阻塞行为,默认为True。如果设置为False,将引发Queue.Empty异常(定义在Queue库模块中)。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引发Queue.Full异常。
q.qsize()
返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。
q.empty()
如果调用此方法时 q为空,返回True。如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。
q.full()
如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的(参考q.empty()方法)。。
from multiprocessing import Process,Queue if __name__ == ‘__main__‘: q = Queue(5) #创建队列 for i in range(5): q.put(i) #放进数据 print(q.full()) #q.put(6) 此处阻塞 for i in range(5): print(q.get()) #获取数据 print(q.empty()) #q.get() 此处阻塞
from multiprocessing import Event,Process,Queue def produce(q): q.put(‘from produce‘) def comsume(q): print(q.get()) if __name__ == ‘__main__‘: q = Queue(5) #创建队列 pro = Process(target=produce,args=(q,)) pro.start() com = Process(target=comsume, args=(q,)) com.start()
from multiprocessing import Process,Queue import time import random def producer(name,goods,q): for i in range(10): time.sleep(random.randint(1,4)) print(‘%s生产了第%s个%s‘%(name,i,goods)) q.put(‘第%s个%s‘%(i,goods)) def comsumer(q,name): while 1: goods = q.get() if goods == None:break print(‘\033[31m%s买了了%s\033[0m‘ % (name,goods)) time.sleep(random.randint(2,6)) if __name__ == ‘__main__‘: q = Queue(10) p = Process(target=producer,args=(‘HSR‘,‘牛奶‘,q)) p2 = Process(target=producer, args=(‘TTT‘, ‘面包‘, q)) c = Process(target=comsumer, args=(q,‘Lisi‘)) c2 = Process(target=comsumer, args=(q, ‘ZhangSan‘)) p.start() p2.start() c.start() c2.start() p.join() p2.join() q.put(None) q.put(None)
from multiprocessing import Process,JoinableQueue import time import random def producer(name,goods,q): for i in range(10): time.sleep(random.randint(1,4)) print(‘%s生产了第%s个%s‘%(name,i,goods)) q.put(‘第%s个%s‘%(i,goods)) q.join() #阻塞,直到队列中的数据被全部执行完毕 def comsumer(q,name): while 1: goods = q.get() if goods == None:break print(‘\033[31m%s买了了%s\033[0m‘ % (name,goods)) time.sleep(random.randint(2,6)) q.task_done() #count - 1 if __name__ == ‘__main__‘: q = JoinableQueue(10) p = Process(target=producer,args=(‘HSR‘,‘牛奶‘,q)) p2 = Process(target=producer, args=(‘TTT‘, ‘面包‘, q)) c = Process(target=comsumer, args=(q,‘Lisi‘)) c2 = Process(target=comsumer, args=(q, ‘ZhangSan‘)) p.start() p2.start() c.daemon = True #设置为守护进程,主进程结束则子进程结束,而这里的主进程等待生产进程的结束 c2.daemon = True #生产进程又等待消费进程消费完。所以消费者消费完了就会结束进程 c.start() c2.start() p.join() p2.join()
2.管道
from multiprocessing import Pipe,Process def func(conn1,conn2): conn2.close() while 1: try: print(conn1.recv()) except EOFError: conn1.close() break if __name__ == ‘__main__‘: conn1, conn2 = Pipe() p1 = Process(target=func,args=(conn1, conn2)) #传给不同进程的conn是不会相互影响的 p1.start() conn1.close() for i in range(20): conn2.send("hi") conn2.close()
#Pipe有数据不安全性 #管道可能出现一端的多个消费者同时取一个数据 #所以可以加上一个进程锁来保证安全性 from multiprocessing import Pipe,Process,Lock import time import random def producer(con,pro,name,goods): con.close() for i in range(8): time.sleep(random.randint(1,3)) print(‘%s生成了第%s个%s‘%(name,i,goods)) pro.send(‘第%s个%s‘%(i,goods)) pro.close() def consumer(con,pro,name,lock): pro.close() while 1: try: lock.acquire() goods = con.recv() lock.release() print(‘%s喝了%s‘%(name,goods)) time.sleep(random.random()) except EOFError: lock.release() #因为最后消费者通过异常来结束进程,所以最后一次的recv后面的lock.release不会执行,所以要在 #这个地方再写一个release() con.close() break if __name__ == ‘__main__‘: con, pro = Pipe() lock = Lock() p = Process(target=producer, args=(con,pro,‘HSR‘,‘牛奶‘)) c = Process(target=consumer, args=(con, pro, ‘TTT‘,lock)) c2 = Process(target=consumer, args=(con, pro, ‘TTT2‘,lock)) p.start() c.start() c2.start() con.close() pro.close()
3.Manager
from multiprocessing import Manager,Process def func(dic): dic[‘count‘] -= 1 print(dic) if __name__ == ‘__main__‘: m = Manager() 创建一个Manger() dic = m.dict({‘count‘:100}) #变成进程共享的字典 p = Process(target=func, args=(dic,)) p.start() p.join() #等待子进程结束
from multiprocessing import Manager,Process,Lock def work(d,lock): with lock: #不加锁而操作共享的数据,肯定会出现数据错乱 d[‘count‘]-=1 if __name__ == ‘__main__‘: lock=Lock() with Manager() as m: dic=m.dict({‘count‘:100}) p_l=[] for i in range(100): p=Process(target=work,args=(dic,lock)) p_l.append(p) p.start() for p in p_l: p.join() print(dic)
四、进程池
numprocess:要创建的进程数,如果省略,将默认使用cpu_count()的值
initializer:是每个工作进程启动时要执行的可调用对象,默认为None
initargs:是要传给initializer的参数组
p.apply(func [, args [, kwargs]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。 ‘‘‘需要强调的是:此操作并不会在所有池工作进程中并执行func函数。如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用p.apply_async()‘‘‘ p.apply_async(func [, args [, kwargs]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。 ‘‘‘此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。‘‘‘ p.close():关闭进程池,防止进一步操作。如果所有操作持续挂起,它们将在工作进程终止前完成 P.jion():等待所有工作进程退出。此方法只能在close()或teminate()之后调用 方法apply_async()和map_async()的返回值是AsyncResul的实例obj。实例具有以下方法 obj.get():返回结果,如果有必要则等待结果到达。timeout是可选的。如果在指定时间内还没有到达,将引发一场。如果远程操作中引发了异常,它将在调用此方法时再次被引发。 obj.ready():如果调用完成,返回True obj.successful():如果调用完成且没有引发异常,返回True,如果在结果就绪之前调用此方法,引发异常 obj.wait([timeout]):等待结果变为可用。 obj.terminate():立即终止所有工作进程,同时不执行任何清理或结束任何挂起工作。如果p被垃圾回收,将自动调用此函数
#map如果要给函数传参数,只能传可迭代对象 from multiprocessing import Pool def func(dic): print(dic) def func2(dic): print(dic+2) if __name__ == ‘__main__‘: pool = Pool(5) #进程数,CPU核心数+1 #如果Pool()不传参数,默认是cpu核心数 pool.map(func2,range(100)) #100个任务 #这里自带join效果 pool.map(func, [‘hsr‘,‘ttt‘]) # 2个任务
from multiprocessing import Pool import os import time def func(n): print(‘[pid:%s]start id:%s‘%(os.getpid(),n)) time.sleep(1.5) print(‘\033[31m[pid:%s]end id:%s\033[0m‘%(os.getpid(),n)) if __name__ == ‘__main__‘: pool = Pool(5) for i in range(10): #pool.apply(func,args=(i,)) #同步 pool.apply_async(func,args=(i,)) #异步。与主进程完全异步,需要手动close和join pool.close() # 结束进程池接收任务 pool.join() # 感知进程中的任务都执行结束
import socket from multiprocessing import Pool def func(conn): while 1: conn.send(b‘hello‘) ret = conn.recv(1024).decode(‘utf-8‘) if ret == ‘q‘: break print(ret) conn.close() if __name__ == ‘__main__‘: sk = socket.socket() sk.bind((‘127.0.0.1‘, 8081)) sk.listen() pool = Pool(5) while 1: conn, addr = sk.accept() pool.apply_async(func,args=(conn,))
import socket sk = socket.socket() sk.connect((‘127.0.0.1‘,8081)) ret = sk.recv(1024).decode(‘utf-8‘) print(ret) c = input().encode(‘utf-8‘) sk.send(c) sk.close()
from multiprocessing import Pool def func(i): return i**2 if __name__ == ‘__main__‘: pool = Pool(5) #使用map的返回值 ret = pool.map(func,range(10)) print(ret) res_l = [] for i in range(10): #同步 # res = pool.apply(func,args=(i,)) #apply的结果就是func的返回值 # print(res) #异步 res = pool.apply_async(func,args=(i,)) #apply_async的结果 #这里如果直接使用res.get()来获取返回值,会阻塞,所以先将其放入列表中,后面再get # print(res.get()) #阻塞等待func的结果 res_l.append(res) for i in res_l: print(i.get())
from multiprocessing import Pool def func(i): print(‘in func1‘) return i**2 def func2(n): print(‘in func2‘) print(n) if __name__ == ‘__main__‘: pool = Pool(5) pool.apply_async(func, args=(10,), callback=func2) #执行func1,把返回值作为fun2的参数执行func2 #回调函数func2在主进程中zhi‘x pool.close() pool.join()
import requests from multiprocessing import Pool def get(url): ret = requests.get(url) if ret.status_code == 200: return ret.content.decode(‘utf-8‘),url def call_back(args): print(args[1] +" "+ str(len(args[0]))) url_lst = [ ‘http://www.cnblog.com‘, ‘https://www.baidu.com‘, ‘http://www.sohu.com‘ ] if __name__ == ‘__main__‘: pool = Pool(5) for i in url_lst: pool.apply_async(get,args=(i,),callback=call_back) pool.close() pool.join()
标签:执行流程 进程终止 生产者消费者模式 定时 代码执行 als 自定义 attribute result
原文地址:https://www.cnblogs.com/walthwang/p/10419134.html