通过实例解析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实现的生成随机迷宫算法核心代码分享(含游戏完整代码)
Jul 11 Python
Python验证企业工商注册码
Oct 25 Python
python中scikit-learn机器代码实例
Aug 05 Python
浅谈python图片处理Image和skimage的区别
Aug 04 Python
Pytorch 实现自定义参数层的例子
Aug 17 Python
安装完Python包然后找不到模块的解决步骤
Feb 13 Python
python输出数学符号实例
May 11 Python
python 字符串的驻留机制及优缺点
Jun 19 Python
Python 读取位于包中的数据文件
Aug 07 Python
Python猫眼电影最近上映的电影票房信息
Sep 18 Python
python基于socket模拟实现ssh远程执行命令
Dec 05 Python
使用pd.merge表连接出现多余行的问题解决
Jun 16 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
《五等分的花嫁》漫画完结!2020年10月第2期TV动画制作组换血!
2020/03/06 日漫
PHP数组操作类实例
2015/07/11 PHP
thinkPHP5 tablib标签库自定义方法详解
2017/05/10 PHP
利用PHPStorm如何开发Laravel应用详解
2017/08/30 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
PHP实现微信小程序用户授权的工具类示例
2019/03/05 PHP
laravel 实现划分admin和home 模块分组
2019/10/15 PHP
关于this和self的使用说明
2010/08/01 Javascript
读jQuery之五(取DOM元素)
2011/06/20 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
jQuery+PHP实现动态数字展示特效
2015/03/14 Javascript
js实现ctrl+v粘贴上传图片(兼容chrome、firefox、ie11)
2016/03/09 Javascript
利用Node.js+Koa框架实现前后端交互的方法
2017/02/27 Javascript
js实现放大镜特效
2017/05/18 Javascript
react组件从搭建脚手架到在npm发布的步骤实现
2019/01/09 Javascript
vue-router命名路由和编程式路由传参讲解
2019/01/19 Javascript
详解JavaScript中分解数字的三种方法
2021/01/05 Javascript
Python collections模块实例讲解
2014/04/07 Python
python实现爬虫统计学校BBS男女比例之多线程爬虫(二)
2015/12/31 Python
Python模块结构与布局操作方法实例分析
2017/07/24 Python
Python爬取当当、京东、亚马逊图书信息代码实例
2017/12/09 Python
用Python进行简单图像识别(验证码)
2018/01/19 Python
Python多线程threading和multiprocessing模块实例解析
2018/01/29 Python
强悍的Python读取大文件的解决方案
2019/02/16 Python
Python使用sax模块解析XML文件示例
2019/04/04 Python
python+rsync精确同步指定格式文件
2019/08/29 Python
Django实现auth模块下的登录注册与注销功能
2019/10/10 Python
Python values()与itervalues()的用法详解
2019/11/27 Python
Python列表操作方法详解
2020/02/09 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
2020/04/07 Python
CSS3实现的渐变幻灯片效果
2020/12/07 HTML / CSS
如何启动时不需输入用户名与密码
2014/05/09 面试题
给客户的道歉信
2014/01/13 职场文书
家长会主持词开场白
2014/03/18 职场文书
电力安全教育培训心得体会
2016/01/11 职场文书
Oracle11g R2 安装教程完整版
2021/06/04 Oracle