通过实例解析python创建进程常用方法


Posted in Python onJune 19, 2020

 运行程序时,单线程或单进程往往是比较慢的,为加快程序运行速度,我们可以使用多进程,可以理解为多任务同时运行,小编的电脑是四核,所以可以设置四个进程。

下面,我们来了解下多进程的使用:

1、使用multiprocessing模块创建进程

multiprocessing模块提供了一个Process类来代表进程对象,语法如下:

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

其中,group:参数未使用,值始终是None

target:表示当前进程启动时执行的可调用对象

name:为当前进程实例的别名

args:表示传递给target函数的参数元组

kwargs:表示传递给target函数的参数字典

使用多进程的一个简单例子:

from multiprocessing import Process   # 导入模块

# 执行子进程代码
def test(interval):
  print('我是子进程')
# 执行主程序
def main():
  print('主进程开始')
  # 实例化Procss进程类
  p = Process(target=test,args=(1,))
  # 启动子进程
  p.start()
  print('主进程结束')

if __name__ == '__main__':
  main()

结果:

主进程开始
主进程结束
我是子进程

Process的实例p常用的方法除start()外,还有如下常用方法:

is_alive():判断进程实例是否还在执行

join([timeout]):是否等待进程实例执行结束,或等待多少秒

start():启动进程实例(创建子进程)

run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法

terminate():不管任务是否完成,立即终止

Process类还有如下常用属性:

name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数

pid:当前进程实例的PID值

下面是Process类方法和属性的使用,创建两个子进程,分别使用os模块和time模块输出父进程和子进程的id以及子进程的时间,并调用Process类的name和pid属性:

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

#两个子进程将会调用的两个方法
def child_1(interval):
  print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getppid()))
  # 计时开始
  t_start = time.time()
  # 程序将会被挂起interval秒
  time.sleep(interval)
  # 计时结束
  t_end = time.time()
  print("子进程(%s)执行时间为'%0.2f'秒"%(os.getpid(),t_end - t_start))

def child_2(interval):
  print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getppid()))
  # 计时开始
  t_start = time.time()
  # 程序将会被挂起interval秒
  time.sleep(interval)
  # 计时结束
  t_end = time.time()
  print("子进程(%s)执行时间为'%0.2f'秒"%(os.getpid(),t_end - t_start))

if __name__ == '__main__':
  print("------父进程开始执行-------")
  # 输出当前程序的ID
  print("父进程PID:%s" % os.getpid())
  # 实例化进程p1
  p1=Process(target=child_1,args=(1,))
  # 实例化进程p2
  p2=Process(target=child_2,name="mrsoft",args=(2,))
  # 启动进程p1
  p1.start()
  # 启动进程p2
  p2.start()
  #同时父进程仍然往下执行,如果p2进程还在执行,将会返回True
  print("p1.is_alive=%s"%p1.is_alive())
  print("p2.is_alive=%s"%p2.is_alive())
  #输出p1和p2进程的别名和PID
  print("p1.name=%s"%p1.name)
  print("p1.pid=%s"%p1.pid)
  print("p2.name=%s"%p2.name)
  print("p2.pid=%s"%p2.pid)
  print("------等待子进程-------")
  # 等待p1进程结束
  p1.join()
  # 等待p2进程结束
  p2.join()
  print("------父进程执行结束-------")

结果:

------父进程开始执行-------
父进程PID:13808
p1.is_alive=True
p2.is_alive=True
p1.name=Process-1
p1.pid=13360
p2.name=mrsoft
p2.pid=21500
------等待子进程-------
子进程(13360)开始执行,父进程为(13808)
子进程(21500)开始执行,父进程为(13808)
子进程(13360)执行时间为'1.01'秒
子进程(21500)执行时间为'2.00'秒
------父进程执行结束-------

上述代码中,第一次实例化Process类时,会为name属性默认赋值为Process-1,第二次则默认为Process-2,但由于实例化进程p2时,设置了name属性为mrsoft,所以p2.name的值为mrsoft。

2、使用Process子类创建进程

对于一些简单的小任务,通常使用Process(target=test)方式实现多进程。但如果要处理复杂任务的进程,通常定义一个类,使其继承Process类,下面是通过使用Process子类创建多个进程。

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

#继承Process类
class SubProcess(Process):
  # 由于Process类本身也有__init__初识化方法,这个子类相当于重写了父类的这个方法
  def __init__(self,interval,name=''):
    # 调用Process父类的初始化方法
    Process.__init__(self)
    # 接收参数interval
    self.interval = interval
    # 判断传递的参数name是否存在
    if name:
      # 如果传递参数name,则为子进程创建name属性,否则使用默认属性
      self.name = name    
  #重写了Process类的run()方法
  def run(self):
    print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid()))
    t_start = time.time()
    time.sleep(self.interval)
    t_stop = time.time()
    print("子进程(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))

if __name__=="__main__":
  print("------父进程开始执行-------")
  # 输出当前程序的ID
  print("父进程PID:%s" % os.getpid())         
  p1 = SubProcess(interval=1,name='mrsoft')
  p2 = SubProcess(interval=2)
  #对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法,
  #所以这里会执行p1.run()
  # 启动进程p1
  p1.start()
  # 启动进程p2
  p2.start() 
  # 输出p1和p2进程的执行状态,如果真正进行,返回True,否则返回False
  print("p1.is_alive=%s"%p1.is_alive())
  print("p2.is_alive=%s"%p2.is_alive())
  #输出p1和p2进程的别名和PID
  print("p1.name=%s"%p1.name)
  print("p1.pid=%s"%p1.pid)
  print("p2.name=%s"%p2.name)
  print("p2.pid=%s"%p2.pid)
  print("------等待子进程-------")
  # 等待p1进程结束
  p1.join()
  # 等待p2进程结束
  p2.join() 
  print("------父进程执行结束-------")

结果:

------父进程开始执行-------
父进程PID:2512
p1.is_alive=True
p2.is_alive=True
p1.name=mrsoft
p1.pid=20328
p2.name=SubProcess-2
p2.pid=13700
------等待子进程-------
子进程(20328) 开始执行,父进程为(2512)
子进程(13700) 开始执行,父进程为(2512)
子进程(20328)执行结束,耗时1.00秒
子进程(13700)执行结束,耗时2.00秒
------父进程执行结束-------

上述代码中,定义了一个SubProcess子类,继承multiprocess.Process父类。SubProcess子类中定义了两个方法:__init__()初始化方法和run()方法,在__init__()初始化方法中,调用父类multiprocess.Process的__init__()初始化方法,否则父类的__init__()方法会被覆盖,无法开启进程。此外,在SubProcess子类中没有定义start()方法,但在主程序中却调用了start()方法,此时就会自动执行SubProcess类的run()方法。

3、使用进程池Pool创建进程

上面我们使用Process类创建了两个进程,但如果要创建十几个或者上百个进程,则需要实例化更多的Process类,解决这一问题的方法就是使用multiprocessing模块提供的pool类,即Pool进程池。

我们先来了解下Pool类的常用方法:

apply_async(func[,args[,kwds]]):使用非阻塞方式调用func()函数(并行执行,阻塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func()函数的参数列表, kwds为传递给func()函数的关键字参数列表

apply(func[,args[,kwds]]):使用阻塞方式调用func()函数

close():关闭Pool,使其不再接受新的任务

terminate():不管任务是否完成,立即终止

join():主进程阻塞,等待子进程的退出,必须在close或terminate之后使用

下面通过一个示例演示一下如何通过进程池创建多进程,设置最大进程数为3,使用非阻塞方式执行10个任务:

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

def task(name):
  print('子进程(%s)执行task %s ...' % ( os.getpid() ,name))
  # 休眠1秒
  time.sleep(1)    

if __name__=='__main__':
  print('父进程(%s).' % os.getpid())
  # 定义一个进程池,最大进程数3
  p = Pool(3)    
  # 从0开始循环10次  
  for i in range(10):
    # 使用非阻塞方式调用task()函数 
    p.apply_async(task, args=(i,))  
  print('等待所有子进程结束...')
  # 关闭进程池,关闭后p不再接收新的请求
  p.close()
  # 等待子进程结束
  p.join()  
  print('所有子进程结束.')

结果:

父进程(3856).
等待所有子进程结束...
子进程(18872)执行task 0 ...
子进程(11220)执行task 1 ...
子进程(10140)执行task 2 ...
子进程(18872)执行task 3 ...
子进程(11220)执行task 4 ...
子进程(10140)执行task 5 ...
子进程(18872)执行task 6 ...
子进程(11220)执行task 7 ...
子进程(10140)执行task 8 ...
子进程(18872)执行task 9 ...
所有子进程结束.

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

Python 相关文章推荐
Python Web框架Flask下网站开发入门实例
Feb 08 Python
python抓取并保存html页面时乱码问题的解决方法
Jul 01 Python
Python 自动化表单提交实例代码
Jun 08 Python
用Python实现随机森林算法的示例
Aug 24 Python
python OpenCV学习笔记实现二维直方图
Feb 08 Python
python分治法求二维数组局部峰值方法
Apr 03 Python
Django 中间键和上下文处理器的使用
Mar 17 Python
Python中使用__new__实现单例模式并解析
Jun 25 Python
使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解
Jan 25 Python
python中Ansible模块的Playbook的具体使用
May 28 Python
Python图像阈值化处理及算法比对实例解析
Jun 19 Python
如何用 Python 处理不平衡数据集
Jan 04 Python
keras model.fit 解决validation_spilt=num 的问题
Jun 19 #Python
为什么是 Python -m
Jun 19 #Python
Python 私有属性和私有方法应用场景分析
Jun 19 #Python
Python基于network模块制作电影人物关系图
Jun 19 #Python
keras中的History对象用法
Jun 19 #Python
python中rc1什么意思
Jun 19 #Python
解决keras backend 越跑越慢问题
Jun 18 #Python
You might like
人大复印资料处理程序_输入篇
2006/10/09 PHP
php chr() ord()中文截取乱码问题解决方法
2008/09/08 PHP
php 智能404跳转代码,适合换域名没改变目录的网站
2010/06/04 PHP
PHP设计模式之代理模式的深入解析
2013/06/13 PHP
PHP 信号管理知识整理汇总
2017/02/19 PHP
IE与firefox之jquery用法区别
2008/10/03 Javascript
Javascript 面向对象 命名空间
2010/05/13 Javascript
ASP.NET jQuery 实例14 在ASP.NET form中校验时间范围
2012/02/03 Javascript
jquery插件开发之实现md5插件
2014/03/17 Javascript
JavaScript中document对象使用详解
2015/01/06 Javascript
自己编写的支持Ajax验证的JS表单验证插件
2015/05/15 Javascript
在vue组件中使用axios的方法
2018/03/16 Javascript
基于jQuery使用Ajax动态执行模糊查询功能
2018/07/05 jQuery
Vue+Mock.js模拟登录和表格的增删改查功能
2018/07/26 Javascript
js时间戳转yyyy-MM-dd HH-mm-ss工具类详解
2019/04/30 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
在Vue中使用this.$store或者是$route一直报错的解决
2019/11/08 Javascript
Python判断Abundant Number的方法
2015/06/15 Python
Python基于百度AI的文字识别的示例
2018/04/21 Python
浅谈Series和DataFrame中的sort_index方法
2018/06/07 Python
对python判断ip是否可达的实例详解
2019/01/31 Python
python学习——内置函数、数据结构、标准库的技巧(推荐)
2019/04/18 Python
在python 中split()使用多符号分割的例子
2019/07/15 Python
django 单表操作实例详解
2019/07/30 Python
Python3如何对urllib和urllib2进行重构
2019/11/25 Python
python-sys.stdout作为默认函数参数的实现
2020/02/21 Python
python3注册全局热键的实现
2020/03/22 Python
Django 解决上传文件时,request.FILES为空的问题
2020/05/20 Python
Expedia马来西亚旅游网站:廉价酒店,度假村和航班预订
2016/07/26 全球购物
德国体育用品网上商店:SC24.com
2016/08/01 全球购物
介绍一下linux的文件系统
2015/10/06 面试题
会计电算化专业自荐信
2014/03/15 职场文书
优秀团员事迹材料1000字
2014/08/20 职场文书
优秀党务工作者先进事迹材料
2014/12/25 职场文书
《我要的是葫芦》教学反思
2016/02/18 职场文书
使用CSS实现音波加载效果
2023/05/07 HTML / CSS