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实现监控程序执行时间并将其写入日志的方法
Jun 30 Python
Python整型运算之布尔型、标准整型、长整型操作示例
Jul 21 Python
python绘制圆柱体的方法
Jul 02 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
Nov 07 Python
Python中利用aiohttp制作异步爬虫及简单应用
Nov 29 Python
python使用正则筛选信用卡
Jan 27 Python
Python求一批字符串的最长公共前缀算法示例
Mar 02 Python
Python使用微信接入图灵机器人过程解析
Nov 04 Python
python向图片里添加文字
Nov 26 Python
使用python切片实现二维数组复制示例
Nov 26 Python
django框架两个使用模板实例
Dec 11 Python
Django实现celery定时任务过程解析
Apr 21 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
PHP自动生成月历代码
2006/10/09 PHP
如何在WIN2K下安装PHP4.04
2006/10/09 PHP
PHP过滤★等特殊符号的正则
2014/01/27 PHP
CI框架中集成CKEditor编辑器的教程
2014/06/09 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
利用JQuery为搜索栏增加tag提示
2009/06/22 Javascript
JS实现同时搜索百度和必应的方法
2015/01/27 Javascript
基于jQuery实现网页打印功能
2015/12/01 Javascript
AngularJS仿苹果滑屏删除控件
2016/01/18 Javascript
JS实现图片平面旋转的方法
2016/03/01 Javascript
下一代Bootstrap的5个特点 超酷炫!
2016/06/17 Javascript
jQuery表单验证插件解析(推荐)
2016/07/21 Javascript
AngularJS教程之简单应用程序示例
2016/08/16 Javascript
js HTML5多媒体影音播放
2016/10/17 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
2018/11/19 Javascript
js根据需要计算数组中重复出现某个元素的个数
2019/01/18 Javascript
VUE中使用MUI方法
2019/02/12 Javascript
vue路由传参页面刷新参数丢失问题解决方案
2019/10/08 Javascript
[17:00]DOTA2 HEROS教学视频教你分分钟做大人-帕克
2014/06/10 DOTA
11月编程语言排行榜 Python逆袭C#上升到第4
2017/11/15 Python
利用python将图片转换成excel文档格式
2017/12/30 Python
Pycharm更换python解释器的方法
2018/10/29 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
2019/02/13 Python
numpy中生成随机数的几种常用函数(小结)
2020/08/18 Python
以实惠的价格轻松租车,免费取消:Easyrentcars
2019/07/16 全球购物
Moda Italia荷兰:意大利男士服装
2019/08/31 全球购物
幼儿园教学管理制度
2014/02/04 职场文书
财务担保书范文
2014/04/02 职场文书
单位工作证明格式模板
2014/10/04 职场文书
2014年标准化工作总结
2014/12/17 职场文书
小学语文新课改心得体会
2016/01/22 职场文书
python调试工具Birdseye的使用教程
2021/05/25 Python
mysql中int(3)和int(10)的数值范围是否相同
2021/10/16 MySQL
Netty客户端接入流程NioSocketChannel创建解析
2022/03/25 Java/Android
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
2022/06/21 Python