python多进程模板
凑合着用吧,可形成多级生产消费者模式,如果子进程结果不需要收集向后传递可以直接使用进程池(本人对进程池不熟,如果有进程池构成生产消费者模式的样例求推荐,感激不尽)
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/2/27 11:40 # @Author : Andes # @Site : import os import traceback from multiprocessing import Process, Queue, Value, Lock import time # 收尾进程,需要收集上一段所有子进程结果时使用,特点是退出循环后无需更新进程结束标志 def op_end(): ################## ##本进程初始化区域## ################## while True: try: [oe1, oen] = opn_queue.get(timeout=0.1) a = oe1 b = oen except Exception as e: if opn_finishmark.value == 1: if opn_queue.empty(): break else: continue else: continue ################# ##本进程收尾区域## ################# # 如需收集所有子进程结果,则后接收尾进程,否则自身写成收尾进程形式(即退出循环后无需更新进程结束标志) def opn(): ################## ##本进程初始化区域## ################## while True: try: [on1, onn] = op2_queue.get(timeout=0.1) a = on1 b = onn opn_queue.put([a, b]) except Exception as e: if op2_finishmark.value == 1: if op2_queue.empty(): break else: continue else: continue ################# ##本进程收尾区域## ################# lockn.acquire() opn_countmark.value += 1 lockn.release() if opn_countmark.value == num_opn: opn_finishmark.value = 1 def op2(): ################## ##本进程初始化区域## ################## while True: try: [o21, o2n] = op1_queue.get(timeout=0.1) a = o21 b = o2n op2_queue.put([a, b]) except Exception as e: if op1_finishmark.value == 1: if op1_queue.empty(): break else: continue else: continue ################# ##本进程收尾区域## ################# lock2.acquire() op2_countmark.value += 1 lock2.release() if op2_countmark.value == num_op2: op2_finishmark.value = 1 def op1(): ################## ##本进程初始化区域## ################## while True: try: [o11, o1n] = input_queue.get(timeout=0.1) # 从某队列取数据 a = o11 b = o1n op1_queue.put([a, b]) # 将数据放入某队列 except Exception as e: # 保证本进程正常退出 if input_finishmark.value == 1: if input_queue.empty(): break else: continue else: continue ################# ##本进程收尾区域## ################# # 下面操作为更新本批子进程完成数,保证op2批次的子进程正常退出,如无后续,则无需下面操作(即收尾进程) lock1.acquire() op1_countmark.value += 1 lock1.release() if op1_countmark.value == num_op1: op1_finishmark.value = 1 def set_input(is1, isn): t = 0 for r, d, f in os.walk(so_rt): if len(f) != 0: for fi in f: if fi.endswith('.jpg') or fi.endswith('.jpeg') or fi.endswith('.png') or fi.endswith('.bmp') or \ fi.endswith('.JPG') or fi.endswith('.JPEG') or fi.endswith('.PNG') or fi.endswith( '.BMP'): t += 1 img_path = os.path.join(r, fi) input_queue.put([img_path, t]) input_finishmark.value += 1 print('insert done {}'.format(t)) so_rt = '/data_b/data_alpen/imgs' # 图片根目录 input_queue = Queue(20) # 输入队列,存储图片路径,括号内为队列容纳的最大元素个数,太大容易爆内存,不填为无上限 input_countmark = Value('i', 0) # 输入完成数 input_finishmark = Value('i', 0) # 输入结束标志 op1_queue = Queue(30) # 中间进程1结果队列 op1_countmark = Value('i', 0) # 中间进程1完成数 op1_finishmark = Value('i', 0) # 中间进程1结束标志 op2_queue = Queue(30) # 中间进程2结果队列 op2_countmark = Value('i', 0) # 中间进程2完成数 op2_finishmark = Value('i', 0) # 中间进程2结束标志 opn_queue = Queue(30) # 中间进程n结果队列 opn_countmark = Value('i', 0) # 中间进程n完成数 opn_finishmark = Value('i', 0) # 中间进程n结束标志 locki = Lock() # 输入进程锁 lock1 = Lock() # 中间进程1锁 lock2 = Lock() # 中间进程2锁 lockn = Lock() # 中间进程n锁 num_i = 1 # 输入进程数 num_op1 = 5 # 中间进程1进程数 num_op2 = 5 # 中间进程2进程数 num_opn = 5 # 中间进程n进程数 num_ope = 1 # 收尾进程数 #&&&&&产生子进程格式为: # Process(target=func, args=(param1, param2,...,paramn,)) # func为子进程操作的函数,后面不带括号,传入参数的末尾建议加逗号 # 若不传入参数则为:Process(target=func) #&&&&&中间进程理论上可以无限拼接 def op_main(): st = time.time() # 输入子进程 is1 = 0 # 输入进程参数1 isn = 0 # 输入进程参数n pi = Process(target=set_input, args=(is1, isn,)) pi.start() # 中间进程1 for p1 in xrange(0, num_op1): pp1 = Process(target=op1) pp1.start() # 中间进程2 for p2 in xrange(0, num_op2): pp2 = Process(target=op2) pp2.start() # 中间进程n for pn in xrange(0, num_opn): ppn = Process(target=opn) ppn.start() # 若需统计总时间,则收尾进程需使用.join()保证主进程在所有收尾进程结束后再继续往下执行, # 若无需统计时间,则跟中间进程一样即可 pl = [] # 收尾进程 for pe in xrange(0, num_ope): ppe = Process(target=op_end) ppe.start() pl.append(ppe) for pli in pl: pli.join() et = time.time() print('all costtime:{}'.format(et-st)) def main(): op_main() if __name__ == '__main__': main()