python多进程实例详解
Posted ustc-zcc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python多进程实例详解相关的知识,希望对你有一定的参考价值。
写在前面:python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。
1.multiprocessing
模块提供了一个Process
类来代表一个进程对象
import os import time import multiprocessing def run_proc(name): # 子进程要执行的代码 print ‘运行子进程 %s ,子进程号为(%s)...‘ % (name, os.getpid()) print "我的处理内容是:%s+%s=?" % (name,name) return name if __name__==‘__main__‘: start = time.time() print ‘父进程号为 %s.‘ % os.getpid() print(‘----------------------------------------‘) job = [] for i in range(3): p = multiprocessing.Process(target=run_proc, args=(i,))#多进程 job.append(p) print ‘子进程%d开启...‘%i p.start() # print ‘子进程%d结束...‘ %i print
#加join()可以让主线程一直等待全部的子线程结束之后,主线程自身才结束,程序退出 for t in job: t.join()#join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步 end = time.time() print end-start
运行结果如下:
父进程号为 4924. ---------------------------------------- 子进程0开启... 子进程0结束... 子进程1开启... 子进程1结束... 子进程2开启... 运行子进程 0 ,子进程号为(5516)... 我的处理内容是:0+0=? 运行子进程 1 ,子进程号为(5517)... 我的处理内容是:1+1=? 运行子进程 2 ,子进程号为(5523)... 我的处理内容是:2+2=? 子进程2结束... 0.0220789909363
如果想要返回多进程process处理得到的结果,只需要利用multiprocessing 中的Manager类即可,稍改代码:
import os import time from multiprocessing import Manager def run_proc(name,return_list): # 子进程要执行的代码 print ‘运行子进程 %s ,子进程号为(%s)...‘ % (name, os.getpid()) print "我的处理内容是:%s+%s=?" % (name,name) return_list.append(name) if __name__==‘__main__‘: print ‘父进程号为 %s.‘ % os.getpid() print(‘----------------------------------------‘) manager = Manager() return_list = manager.list() #return_dict = manager.dict() 也可以使用字典dict job = [] for i in range(3): p = multiprocessing.Process(target=run_proc, args=(i,return_list))#多进程 job.append(p) print ‘子进程%d开启...‘%i p.start() print ‘子进程%d结束...‘ %i print for t in job: t.join() print "所有子进程处理得到的结果都在return_list中,值为:",return_list
运行结果如下:
父进程号为 4924. ---------------------------------------- 子进程0开启... 子进程0结束... 子进程1开启... 子进程1结束... 子进程2开启... 运行子进程 0 ,子进程号为(5614)... 我的处理内容是:0+0=? 运行子进程 1 ,子进程号为(5616)... 我的处理内容是:1+1=? 运行子进程 2 ,子进程号为(5623)... 我的处理内容是:2+2=? 子进程2结束... 所有子进程处理得到的结果都在return_list中,值为: [0, 1, 2]
2.Pool:如果要启动大量的子进程,可以用进程池的方式批量创建子进程:
from multiprocessing import Pool import os, time, random def long_time_task(name): print ‘运行任务 %s ,子进程号为(%s)...‘ % (name, os.getpid()) print "我就是子进程号为(%s)处理的内容" % (os.getpid()) start = time.time() time.sleep(random.random() * 3) end = time.time() print ‘任务 %s 运行了 %0.2f 秒.‘ % (name, (end - start)) return name if __name__==‘__main__‘: print ‘父进程号为 %s.‘ % os.getpid() rst = [] p = Pool(4) #进程池中含有4个子进程 for i in range(5): #4个子进程完成5个任务,所以有一个任务是需要等某个进程空闲再处理 a = p.apply_async(long_time_task, args=(i,)) #a是进程处理函数long_time_task的返回结果 rst.append(a) #将次得到的结果添加到数组rst中去 print ‘等待所有子进程结束...‘ p.close() p.join()#等待所有子进程执行完毕。调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。 print ‘所有子进程结束...‘
运行结果如下:
父进程号为 3378. 运行任务 0 ,子进程号为(4621)... 运行任务 2 ,子进程号为(4624)... 运行任务 1 ,子进程号为(4622)... 我就是子进程号为(4621)处理的内容 我就是子进程号为(4622)处理的内容 运行任务 3 ,子进程号为(4627)... 我就是子进程号为(4624)处理的内容 我就是子进程号为(4627)处理的内容 任务 1 运行了 0.16 秒. 运行任务 4 ,子进程号为(4622)... 我就是子进程号为(4622)处理的内容 等待所有子进程结束... 任务 2 运行了 0.98 秒. 任务 4 运行了 0.89 秒. 任务 3 运行了 2.25 秒. 任务 0 运行了 2.89 秒. 所有子进程结束...
直接输出rst不会得到想要的结果:
rst 运行结果: [<multiprocessing.pool.ApplyResult at 0x7ffa6c682c90>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587590>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587610>, <multiprocessing.pool.ApplyResult at 0x7ffa6c5876d0>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587790>]
这是需要用到.get()方法:
rst = [i.get() for i in rst] rst 运行结果: [0, 1, 2, 3, 4]
以上是关于python多进程实例详解的主要内容,如果未能解决你的问题,请参考以下文章
python子进程模块subprocess详解与应用实例 之二