(1条消息) Python 多进程 multiprocessing.Pool类详解

multiprocessing模块

multiprocessing包是Python中的多进程管理包。它与 threading.Thread类似,可以利用multiprocessing.Process对象来创建一个进程。该进程可以允许放在Python程序内部编写的函数中。该Process对象与Thread对象的用法相同,拥有is_alive()、join([timeout])、run()、start()、terminate()等方法。属性有:authkey、daemon(要通过start()设置)、exitcode(进程在运行时为None、如果为–N,表示被信号N结束)、name、pid。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类,用来同步进程,其用法也与threading包中的同名类一样。multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。

这个模块表示像线程一样管理进程,这个是multiprocessing的核心,它与threading很相似,对多核CPU的利用率会比threading好的多。

看一下Process类的构造方法:

__init__(self, group=None, target=None, name=None, args=(), kwargs={})

参数说明:
group:进程所属组。基本不用
target:表示调用对象。
args:表示调用对象的位置参数元组。
name:别名
kwargs:表示调用对象的字典。

创建进程的简单实例:

#coding=utf-8import multiprocessingdef do(n) :  #获取当前线程的名字  name = multiprocessing.current_process().name  print name,'starting'  print "worker ", n  return if __name__ == '__main__' :  numList = []  for i in xrange(5) :    p = multiprocessing.Process(target=do, args=(i,))    numList.append(p)    p.start()    p.join()    print "Process end."

执行结果:

Process-1 startingworker  0Process end.Process-2 startingworker  1Process end.Process-3 startingworker  2Process end.Process-4 startingworker  3Process end.Process-5 startingworker  4Process end.

创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,并用其start()方法启动,这样创建进程比fork()还要简单。
join()方法表示等待子进程结束以后再继续往下运行,通常用于进程间的同步。

注意:
在Windows上要想使用进程模块,就必须把有关进程的代码写在当前.py文件的if __name__ == ‘__main__’ :语句的下面,才能正常使用Windows下的进程模块。Unix/Linux下则不需要。

Pool类

在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量的时间。如果操作的对象数目不大时,还可以直接使用Process类动态的生成多个进程,十几个还好,但是如果上百个甚至更多,那手动去限制进程数量就显得特别的繁琐,此时进程池就派上用场了。
Pool类可以提供指定数量的进程供用户调用,当有新的请求提交到Pool中时,如果池还没有满,就会创建一个新的进程来执行请求。如果池满,请求就会告知先等待,直到池中有进程结束,才会创建新的进程来执行这些请求。
下面介绍一下multiprocessing 模块下的Pool类下的几个方法

apply()

函数原型:

apply(func[, args=()[, kwds={}]])

该函数用于传递不定参数,主进程会被阻塞直到函数执行结束(不建议使用,并且3.x以后不在出现)。

apply_async()

函数原型:

apply_async(func[, args=()[, kwds={}[, callback=None]]])

与apply用法一样,但它是非阻塞且支持结果返回进行回调。

map()

函数原型:

map(func, iterable[, chunksize=None])

Pool类中的map方法,与内置的map函数用法行为基本一致,它会使进程阻塞直到返回结果。
注意,虽然第二个参数是一个迭代器,但在实际使用中,必须在整个队列都就绪后,程序才会运行子进程。

close()

关闭进程池(pool),使其不在接受新的任务。

terminate()

结束工作进程,不在处理未处理的任务。

join()

主进程阻塞等待子进程的退出,join方法必须在close或terminate之后使用。

multiprocessing.Pool类的实例:

import timefrom multiprocessing import Pooldef run(fn):  #fn: 函数参数是数据列表的一个元素  time.sleep(1)  return fn*fnif __name__ == "__main__":  testFL = [1,2,3,4,5,6]    print 'shunxu:' #顺序执行(也就是串行执行,单进程)  s = time.time()  for fn in testFL:    run(fn)  e1 = time.time()  print "顺序执行时间:", int(e1 - s)  print 'concurrent:' #创建多个进程,并行执行  pool = Pool(5)  #创建拥有5个进程数量的进程池  #testFL:要处理的数据列表,run:处理testFL列表中数据的函数  rl =pool.map(run, testFL)   pool.close()#关闭进程池,不再接受新的进程  pool.join()#主进程阻塞等待子进程的退出  e2 = time.time()  print "并行执行时间:", int(e2-e1)  print rl

执行结果:

shunxu:顺序执行时间: 6concurrent:并行执行时间: 2[1, 4, 9, 16, 25, 36]

上例是一个创建多个进程并发处理与顺序执行处理同一数据,所用时间的差别。从结果可以看出,并发执行的时间明显比顺序执行要快很多,但是进程是要耗资源的,所以平时工作中,进程数也不能开太大。
程序中的r1表示全部进程执行结束后全局的返回结果集,run函数有返回值,所以一个进程对应一个返回结果,这个结果存在一个列表中,也就是一个结果堆中,实际上是用了队列的原理,等待所有进程都执行完毕,就返回这个列表(列表的顺序不定)。
对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),让其不再接受新的Process了。

再看一个实例:

import timefrom multiprocessing import Pooldef run(fn) :  time.sleep(2)  print fnif __name__ == "__main__" :  startTime = time.time()  testFL = [1,2,3,4,5]  pool = Pool(10)#可以同时跑10个进程  pool.map(run,testFL)  pool.close()  pool.join()     endTime = time.time()  print "time :", endTime - startTime

执行结果:

21345time : 2.51999998093

再次执行结果如下:

13425time : 2.48600006104

结果中为什么还有空行和没有折行的数据呢?其实这跟进程调度有关,当有多个进程并行执行时,每个进程得到的时间片时间不一样,哪个进程接受哪个请求以及执行完成时间都是不定的,所以会出现输出乱序的情况。那为什么又会有没这行和空行的情况呢?因为有可能在执行第一个进程时,刚要打印换行符时,切换到另一个进程,这样就极有可能两个数字打印到同一行,并且再次切换回第一个进程时会打印一个换行符,所以就会出现空行的情况。

进程实战实例

并行处理某个目录下文件中的字符个数和行数,存入res.txt文件中,
每个文件一行,格式为:filename:lineNumber,charNumber

import osimport timefrom multiprocessing import Pooldef getFile(path) :  #获取目录下的文件list  fileList = []  for root, dirs, files in list(os.walk(path)) :    for i in files :      if i.endswith('.txt') or i.endswith('.10w') :        fileList.append(root + "\\" + i)  return fileListdef operFile(filePath) :  #统计每个文件中行数和字符数,并返回  filePath = filePath  fp = open(filePath)  content = fp.readlines()  fp.close()  lines = len(content)  alphaNum = 0  for i in content :    alphaNum += len(i.strip('\n'))  return lines,alphaNum,filePathdef out(list1, writeFilePath) :  #将统计结果写入结果文件中  fileLines = 0  charNum = 0  fp = open(writeFilePath,'a')  for i in list1 :    fp.write(i[2] + " 行数:"+ str(i[0]) + " 字符数:"+str(i[1]) + "\n")    fileLines += i[0]    charNum += i[1]  fp.close()  print fileLines, charNumif __name__ == "__main__":  #创建多个进程去统计目录中所有文件的行数和字符数  startTime = time.time()  filePath = "C:\\wcx\\a"  fileList = getFile(filePath)  pool = Pool(5)    resultList =pool.map(operFile, fileList)    pool.close()  pool.join()  writeFilePath = "c:\\wcx\\res.txt"  print resultList  out(resultList, writeFilePath)  endTime = time.time()  print "used time is ", endTime - startTime

执行结果:

耗时不到1秒,可见多进程并发执行速度是很快的。

(0)

相关推荐

  • 【Python从入门到精通】(二十五)Python多进程的使用

    [Python从入门到精通](二十五)Python多进程的使用 您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本篇重点介绍Python多进程的使用,读者朋友们可以将多进程和多线程两者做一个对比 ...

  • 编程语言Python进程和线程保姆式教学,1个台机子多只手干活的秘籍

    进程线程有多重要?刚开始学Python的时候你可能还没有感觉到,因为你写的代码从上到下执行一遍就可以了,但实际上这很初级,实际开发写项目的时候,为了充分利用电脑配置来加快程序进度,我们往往会用到多进程 ...

  • 第52天:Python multiprocessing 模块

    本节主要介绍 multiprocessing 多进程模块,由于 threading 多线程模块无法充分利用电脑的多核优势,而在实际开发中会对系统性能有较高的要求,就需要使用多进程来充分利用多核 cpu ...

  • 一分钟了解 Python 中的并行计算

    Python 以极高的开发效率著称,而运行速度则"没那么快". 虽然,在现代计算机体系架构下,系统的运行效率并不完全取决于编程语言,但程序员仍有可能从编程技巧着手,让自己的代码&q ...

  • (1条消息) python多进程并发与pool多线程

    一.多进程: 当计算机运行程序时,就会创建包含代码和状态的进程.这些进程会通过计算机的一个或多个CPU执行.不过,同一时刻每个CPU只会执行一个进程,然后不同进程间快速切换,给我们一种错觉,感觉好像多 ...

  • (7条消息) linux send与recv函数详解

    转载地址: http://blog.csdn.net/sjin_1314/article/details/9565743 [csharp]  view plain  copy   print ? 1  ...

  • (3条消息) M1卡区块控制位详解

    M1卡区块控制位详解 Mifare 1S50/Mifare 1S70 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取 控制.存取控制为4个字节,共32位,扇区中的每个块(包括 ...

  • (8条消息) Qt学习:QAction系列详解

    一.QAction类详解 [详细描述] QAction类提供了抽象的用户界面action,这些action可以被放置在窗口部件中. 应用程序可以通过菜单,工具栏按钮以及键盘快捷键来调用通用的命令.由于 ...

  • (6条消息) SSD硬盘的接口区别详解图解 SATA、mSATA、PCI

    转 扫盲:SATA.mSATA .PCIe和M.2--SSD硬盘的接口 2019年03月02日 20:47:06 nedwons 阅读数 11035更多 个人分类: 非技术 SATAT通道:硬盘--内 ...

  • (33条消息) 汉字常用特征的提取方法详解

    汉字模板制作: 汉字模板即是对字模图片进行特征提取,将特征数据存放到存储器上构成模板.模板制作与提取待识别汉字特征需要将原始汉字图片进行归一化,可增加特征的鲁棒性.汉字数据尺度归一化到为64*64,归 ...

  • (3条消息) Python实现

    二次函数拟合--最小二乘法公式法 与线性回归相似,对二次函数进行拟合某种意义上也只是加了一个函数,虽然求解的方程变得更加繁琐,需要准备的变量也增加到了七个. 思路有借鉴于:最小二乘法拟合二次曲线 C语 ...

  • (1条消息) python常见图形代码可视化大全整理(包括动图)更新中...

    目录 一.离散型变量的可视化 1 饼图 1.1 matplotlib模块 1.2 panda模块 2 条形图 2.1 matplotlib模块 2.1.1 垂直或水平条形图 2.1.2 堆叠条形图 2 ...

  • (2条消息) Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)

    ahilll 2018-08-09 10:11:22 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 二.Tkinte ...