python实现多进程代码示例


Posted in Python onOctober 31, 2018

想要充分利用多核CPU资源,Python中大部分情况下都需要使用多进程,Python中提供了multiprocessing这个包实现多进程。multiprocessing支持子进程、进程间的同步与通信,提供了Process、Queue、Pipe、Lock等组件。

开辟子进程

multiprocessing中提供了Process类来生成进程实例

Process([group [, target [, name [, args [, kwargs]]]]])

  • group分组,实际上不使用
  • target表示调用对象,你可以传入方法的名字
  • args表示给调用对象以元组的形式提供参数,比如target是函数a,他有两个参数m,n,那么该参数为args=(m, n)即可
  • kwargs表示调用对象的字典
  • name是别名,相当于给这个进程取一个名字

先来个小例子:

# -*- coding:utf-8 -*-
from multiprocessing import Process, Pool
import os
import time


def run_proc(wTime):
  n = 0
  while n < 3:
    print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())  #获取当前进程号和正在运行是的时间
    time.sleep(wTime)  #等待(休眠)
    n += 1

if __name__ == "__main__":
  p = Process(target=run_proc, args=(2,)) #申请子进程
  p.start()   #运行进程
  print "Parent process run. subProcess is ", p.pid
  print "Parent process end,{0}".format(time.ctime())

运行结果:

Parent process run. subProcess is 30196
Parent process end,Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:21 2017
subProcess 30196 run, Mon Mar 27 11:20:23 2017
subProcess 30196 run, Mon Mar 27 11:20:25 2017

根据运行结果可知,父进程运行结束后子进程仍然还在运行,这可能造成僵尸( zombie)进程。

通常情况下,当子进程终结时,它会通知父进程,清空自己所占据的内存,并在内核里留下自己的退出信息。父进程在得知子进程终结时,会从内核中取出子进程的退出信息。但是,如果父进程早于子进程终结,这可能造成子进程的退出信息滞留在内核中,子进程成为僵尸(zombie)进程。当大量僵尸进程积累时,内存空间会被挤占。

有什么办法可以避免僵尸进程呢?

这里介绍进程的一个属性 deamon,当其值为TRUE时,其父进程结束,该进程也直接终止运行(即使还没运行完)。
所以给上面的程序加上p.deamon = true,看看效果。

# -*- coding:utf-8 -*-
from multiprocessing import Process, Pool
import os
import time


def run_proc(wTime):
  n = 0
  while n < 3:
    print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
    time.sleep(wTime)
    n += 1

if __name__ == "__main__":
  p = Process(target=run_proc, args=(2,))
  p.daemon = True  #加入daemon
  p.start()
  print "Parent process run. subProcess is ", p.pid
  print "Parent process end,{0}".format(time.ctime())

执行结果:

Parent process run. subProcess is 31856
Parent process end,Mon Mar 27 11:40:10 2017

这是问题又来了,子进程并没有执行完,这不是所期望的结果。有没办法将子进程执行完后才让父进程结束呢?

这里引入p.join()方法,它使子进程执行结束后,父进程才执行之后的代码

# -*- coding:utf-8 -*-
from multiprocessing import Process, Pool
import os
import time


def run_proc(wTime):
  n = 0
  while n < 3:
    print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
    time.sleep(wTime)
    n += 1

if __name__ == "__main__":
  p = Process(target=run_proc, args=(2,))
  p.daemon = True
  p.start()
  p.join()  #加入join方法
  print "Parent process run. subProcess is ", p.pid
  print "Parent process end,{0}".format(time.ctime())

执行结果:

subProcess 32076 run, Mon Mar 27 11:46:07 2017
subProcess 32076 run, Mon Mar 27 11:46:09 2017
subProcess 32076 run, Mon Mar 27 11:46:11 2017
Parent process run. subProcess is 32076
Parent process end,Mon Mar 27 11:46:13 2017

这样所有的进程就能顺利的执行了。

将进程定义成类

通过继承Process类,来自定义进程类,实现run方法。实例p通过调用p.start()时自动调用run方法。

如下:

# -*- coding:utf-8 -*-
from multiprocessing import Process, Pool
import os
import time


class Myprocess(Process):

  def __init__(self, wTime):
    Process.__init__(self)
    self.wTime = wTime

  def run(self):
    n = 0
    while n < 3:
      print "subProcess %s run," % os.getpid(), "{0}".format(time.ctime())
      time.sleep(self.wTime)
      n += 1


if __name__ == "__main__":
  p = Myprocess(2)
  p.daemon = True
  p.start()  #自动调用run方法
  p.join()
  print "Parent process run. subProcess is ", p.pid
  print "Parent process end,{0}".format(time.ctime())

执行结果和上一个例子相同。

创建多个进程

很多时候系统都需要创建多个进程以提高CPU的利用率,当数量较少时,可以手动生成一个个Process实例。当进程数量很多时,或许可以利用循环,但是这需要程序员手动管理系统中并发进程的数量,有时会很麻烦。这时进程池Pool就可以发挥其功效了。可以通过传递参数限制并发进程的数量,默认值为CPU的核数。

直接上例子:

# -*- coding:utf-8 -*-
from multiprocessing import Process,Pool
import os,time

def run_proc(name):    ##定义一个函数用于进程调用
  for i in range(5):  
    time.sleep(0.2)  #休眠0.2秒
    print 'Run child process %s (%s)' % (name, os.getpid())
#执行一次该函数共需1秒的时间

if __name__ =='__main__': #执行主进程
  print 'Run the main process (%s).' % (os.getpid())
  mainStart = time.time() #记录主进程开始的时间
  p = Pool(8)      #开辟进程池
  for i in range(16):                 #开辟14个进程
    p.apply_async(run_proc,args=('Process'+str(i),))#每个进程都调用run_proc函数,
                            #args表示给该函数传递的参数。

  print 'Waiting for all subprocesses done ...'
  p.close() #关闭进程池
  p.join() #等待开辟的所有进程执行完后,主进程才继续往下执行
  print 'All subprocesses done'
  mainEnd = time.time() #记录主进程结束时间
  print 'All process ran %0.2f seconds.' % (mainEnd-mainStart) #主进程执行时间

执行结果:

开头部分

Run the main process (30920).
Waiting for all subprocesses done …
Run child process Process0 (32396)
Run child process Process3 (25392)
Run child process Process1 (28732)
Run child process Process2 (32436)

末尾部分:

Run child process Process15 (25880)
All subprocesses done
All process last 2.49 seconds.

相关说明:

这里进程池对并发进程的限制数量为8个,而程序运行时会产生16个进程,进程池将自动管理系统内进程的并发数量,其余进程将会在队列中等待。限制并发数量是因为,系统中并发的进程不是越多越好,并发进程太多,可能使CPU大部分的时间用于进程调度,而不是执行有效的计算。

采用多进程并发技术时,就单个处理机而言,其对进程的执行是串行的。但具体某个时刻哪个进程获得CPU资源而执行是不可预知的(如执行结果的开头部分,各进程的执行顺序不定),这就体现了进程的异步性。

如果单个程序执行14次run_proc函数,那么它会需要至少16秒,通过进程的并发,这里只需要2.49秒,可见并发的优势。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中IPYTHON入门实例
May 11 Python
python用reduce和map把字符串转为数字的方法
Dec 19 Python
Python 数据处理库 pandas 入门教程基本操作
Apr 19 Python
python统计多维数组的行数和列数实例
Jun 23 Python
python读取.mat文件的数据及实例代码
Jul 12 Python
python 数据提取及拆分的实现代码
Aug 26 Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
Oct 30 Python
python为Django项目上的每个应用程序创建不同的自定义404页面(最佳答案)
Mar 09 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
Mar 25 Python
Python改变对象的字符串显示的方法
Aug 01 Python
详解python中的闭包
Sep 07 Python
Python datetime模块的使用示例
Feb 02 Python
Python UnboundLocalError和NameError错误根源案例解析
Oct 31 #Python
python多进程控制学习小结
Oct 31 #Python
在Python中实现替换字符串中的子串的示例
Oct 31 #Python
python创建文件时去掉非法字符的方法
Oct 31 #Python
python3 中文乱码与默认编码格式设定方法
Oct 31 #Python
解决python中 f.write写入中文出错的问题
Oct 31 #Python
[原创]Python入门教程3. 列表基本操作【定义、运算、常用函数】
Oct 30 #Python
You might like
在Mac OS上搭建Nginx+PHP+MySQL开发环境的教程
2015/12/21 PHP
改善你的jQuery的25个步骤 千倍级效率提升
2010/02/11 Javascript
js封装的textarea操作方法集合(兼容很好)
2010/11/16 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
jquery自动切换tabs选项卡的具体实现
2013/12/24 Javascript
jQuery 移动端artEditor富文本编辑器
2016/01/11 Javascript
js实现用户输入的小写字母自动转大写字母的方法
2017/01/21 Javascript
关于vue-resource报错450的解决方案
2017/07/24 Javascript
JavaScript实现短信倒计时60s
2017/10/09 Javascript
微信小程序显示倒计时功能示例【测试可用】
2018/12/03 Javascript
微信实现自动跳转到用其他浏览器打开指定APP下载
2019/02/15 Javascript
从0到1构建vueSSR项目之node以及vue-cli3的配置
2019/03/07 Javascript
vue实现密码显示与隐藏按钮的自定义组件功能
2019/04/23 Javascript
[55:45]DOTA2上海特级锦标赛D组败者赛 Liquid VS COL第一局
2016/02/28 DOTA
[03:01]完美盛典趣味短片 DOTA2年度最佳&拉胯英雄
2019/12/07 DOTA
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
2019/04/01 Python
wxPython实现绘图小例子
2019/11/19 Python
pytorch实现对输入超过三通道的数据进行训练
2020/01/15 Python
Python基于Twilio及腾讯云实现国际国内短信接口
2020/06/18 Python
python中的错误如何查看
2020/07/08 Python
美国婚礼礼品网站:MyWeddingFavors
2018/09/26 全球购物
彪马荷兰官网:PUMA荷兰
2019/05/08 全球购物
求最大连续递增数字串(如"ads3sl456789DF3456ld345AA"中的"456789")
2015/09/11 面试题
工程业务员工作职责
2013/12/07 职场文书
法制报告会主持词
2014/04/02 职场文书
新闻传播专业求职信
2014/07/22 职场文书
2015大学生自我评价范文
2015/03/03 职场文书
办公室岗位职责范本
2015/04/11 职场文书
先进基层党组织主要事迹材料
2015/11/03 职场文书
2016年学校“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书
2016年安全月活动总结
2016/04/06 职场文书
用 Python 元类的特性实现 ORM 框架
2021/05/19 Python
mapstruct的用法之qualifiedByName示例详解
2022/04/06 Java/Android
Python中Schedule模块使用详解 周期任务神器
2022/04/19 Python
Python可视化动图组件ipyvizzu绘制惊艳的可视化动图
2022/04/21 Python