python 多进程与进程池
多进程:
导入包:from multiprocessing import Process, Queue,Manager
函数式使用法:
def abc(abc,bcd):
print(abc,bcd)
return abc,bcd
基本调用:
res = Process(target=abc,args=(abc,bcd)) # 传入函数名,参数使用元组的形式写后面
res.start() # 启动
res.join() # 等待进程运行结束
res.close() # 关闭进程
多次调用:
res_list=[]
for i in range(20):
res = Process(target=abc,args=(i,i+1))
res.start()
res_list.append(res)
for res in res_list:
res.jion()
类式调用:
在类中写一个run() 函数,然后调用run,方法同上
消息队列:
q = Queue(N)
q.maxsize # 队列最大数,python3.7中使用
q._maxsize # python 3.9中使用
q.qsize() #队列中当前消息数
q.full() # 队列满 返回True
q.empty() # 队列空 返回True
q.put('abc') # 向队列中添加消息
q.get() # 从队列中取消息
进程池:
导入包:from concurrent.futures import ProcessPoolExecutor
pool = ProcessPoolExecutor(5) # 创建容量为5的进程池,默认大小为cpu核心数
def abc(name,age):
print(name,age)
return name,age
def callback(a):
for i in a.result():
print(i)
return 'abc'
pool.submit(abc,name,age) # abc 为函数名,name,age为函数的参数,有几个跟几个
res = poo.submit(abc,name,age).add__done_callback(callback)
# 提交任务时后面可以跟一个回调函数,abc的返回值以元组的形式直接传递给回调函数,回调函数返回值可能是一个元组(待测试)
消息队列与进程池结合使用:
优点:只使用进程池,无法获取等待执行的任务数量
结合消息队列,可以获得队列中等待的数量
可能出现的问题:从队列向进程池提交任务时,由于队列中的数量是变化的,有可能造成提交数大于进程池大小
def putq(n,q):  #用于向队列中添加任务的函数
      j = 0
      while True:
            for i in range(n):
                  j += 1
                  q.put(j)
    time.sleep(10)
def pro(runningnum):  # 向进程池中提交的任务
      print('pro q.get',runningnum)
  time.sleep(1)  # 延时1秒
  print()      # 输出空行,便观察
def startpro(pro, q):  # 进程池主函数,在主进程中直接调用,如果另外开一个进程可能报错
      Num = 4  # 进程池大小
      pool = ProcessPoolExecutor(Num)  # 创建进程池
      runningnum = 0  # 进程池中正在运行的任务数
      plist = []  # 用于存放 进程池 中运行的任务
      while True:
          # 如果队列非空,并且进程池运行任务数不满,则提交任务
          if (not q.empty()) and (runningnum < Num):
                numtosubmit = Num - runningnum  # 进程池 的空余数
                if numtosubmit > q.qsize():  # 空余数与队列中任务数比较
                      numtosubmit = q.qsize()  # 空余数大于任务数则提交队列中的任务数
                else:
                      pass
                for i in range(numtosubmit):  # 循环提交
                      runningnum += 1  # 运行数 + 1
                      a = q.get()  # 从队列中取任务作为向进程池提交任务的参数
                      res = pool.submit(pro, a)
                      plist.append(res)  # 把进程池任务对象存入列表中
          elif q.empty():
                pass
          for res in plist:  # 如果进程池中的任务对象完成,则从列表中删除并把运行数-1
                if res.done():
                      print(res)
                      plist.remove(res)
                      runningnum -= 1
 
if __name__ == '__main__':  # 进程池方式
      q = Manager().Queue(20)  # 此处需要先调用Manager,否则会报错
      n = 10  # 队列大小
      p = Process(target=putq, args=(10, q))  # 另开一个进程,间隔10秒向队列中添加任务
      p.start()
      time.sleep(2)
      startpro(pro, q)  # 开始进程池进程
队列与多进程结合:
def add_item(item,q):  # 向队列中提交任务
  print('pro q.put',item)
  q.put(item)
  time.sleep(1)  # 延时1秒
  print()      # 输出空行,便观察
def pro(runningnum):  # 向进程中提交的任务
  print('pro q.get',runningnum)
  time.sleep(1)  # 延时1秒
  print()      # 输出空行,便观察
def startpro(pro, n,q):  # 多进程主函数,在主进程中直接调用
  plist = [] # 用于存放 进程池 中运行的任务
  while True:
  # 如果队列非空,并且进程池运行任务数不满,则提交任务
  if (not q.empty()) and (len(plist) < Num):
    numtosubmit = Num - len(plist)  # 进程池 的空余数
    if numtosubmit > q.qsize(): # 空余数与队列中任务数比较
      numtosubmit = q.qsize() # 空余数大于任务数则提交队列中的任务数
    else:
      pass
    for i in range(numtosubmit): # 循环提交
      a = q.get() # 从队列中取任务作为向进程池提交任务的参数
      res = Process(target=startpro,args=(len(plist))
      res.start()
      plist.append(res) # 把进程任务对象存入列表中
  # 注意此处缩进,在需要启动的进程启动完成后,跳出if 后调用jion
  for res in plist: # 提交完成后,把进程jion
    res.jion()
  for res in plist: # 如果进程中的任务对象完成,则从列表中删除并把运行数-1
    if res.is_alive():
      res.close()
      plist.remove(res)
      continue
  if q.empty() and len(plist) == 0:
print('all is over')
break
else:
continue
if __name__ == '__main__':  # 多进程方式
  n = 10  # 队列大小
  q = Manager().Queue(n)  # 此处需要先调用Manager,否则会报错
  p = Process(target=add_item, args=(n, q))  # 另开一个进程,间隔10秒向队列中添加任务
  p.start()
  time.sleep(2)  # 延时 等待任务添加到队列中
  p.jion()
  startpro(pro, n,q)  # 开始进程池进程
p.close()
                    
                
                
            
        
浙公网安备 33010602011771号