Python语法学习之进程的创建与常用方法详解


Posted in Python onApril 08, 2022

该章节我们来学习一下在 Python 中去创建并使用多进程的方法,通过学习该章节,我们将可以通过创建多个进程来帮助我们提高脚本执行的效率。可以认为缩短脚本执行的时间,就是提高执行我们脚本的效率。接下来让我们都看一下今天的章节知识点都有哪些?

进程的创建模块 - multiprocessing

创建进程函数 - Process

函数名 介绍 参数 返回值
Process 创建一个进程 target, args 进程对象

Process功能介绍:实例化一个对象;它需要传入两个参数 target 与 args:target 是一个函数,args 是对应一个函数的参数(args参数是一个元组)。其实我们可以这样去理解,在一个脚本中创建子进程,目的是为了让它执行我们脚本中的某个函数。换句话讲,我们将脚本中的某一个函数单独的启用一个进程去执行。

我们说过进程之间互不干扰,可以同时执行。所以我们可以认为主进程中的程序和子进程的函数是相互不干扰的,听起来可能很难理解,一会儿下文我们进行一个案例的小练习,一遍帮助大家去更好的理解其中的含义。

进程的常用方法

函数名 介绍 参数 返回值
start 执行进程
join 阻塞进程
kill 杀死进程
is_alive 判断进程是否存活 bool
  • start 函数:通过调用它,可以直接启动我们创建的进程。它会马上执行我们进程中传入的函数,start 函数没有任何参数,也没有返回值。
  • join 函数:我们说过,主进程和子进程的程序会同时运行,互不影响。这样就会有一个问题,有可能是 子进程 先执行完它的业务,也有可能是 主进程 先执行完它的业务逻辑。如果有的时候我们必须要先执行完 子进程的业务 再执行 主进程的业务 。则通过调用 join 函数,在这一函数下面执行的主进程业务要等待子进程完成之后才会继续执行。我们将 join 这样的函数叫做 等待/阻塞函数。join 函数没有任何参数,也没有返回值。
  • kill 函数:如果我们在执行子进程的过程中发现不需要这个子进程继续运行了,就可以使用 kill 函数杀死当前的这个子进程,杀死的这个子进程不会在执行子进程中函数的业务逻辑。kill 函数没有任何参数,也没有返回值。
  • is_alive 函数:通过调用这个函数可以判断当前的进程是否是存活状态,它返回一个 bool 值。True 表示当前进程还在,程序还在继续执行;如果是 False 则代表当前进程已经结束了

start 函数

演示案例:

  • 我们先定义两个简单的函数,每个函数定义两个简单的 for 循环。
  • 每执行一次循环,休眠一秒的时间。
  • 在两次循环的开始定义一个实例化时间对象,用以计算两次循环的时间间隔。
  • 同时,获取脚本执行的进程号; 看看是一个怎样的结果。
# coding:utf-8


import time
import os


def work_for_first():

    for i in range(5):
        print('\'work_for_first\' 函数的循环值:%s', '进程号为:%s' % i, os.getpid())	# os.getpid() 为获取进程号函数
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print('\'work_for_second\' 函数的循环值:%s',  '进程号为:%s' % i, os.getpid())
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 获取执行 循环 之前的时间戳
    work_for_first()
    work_for_second()
    end_time = time.time() - start_time     # 获取执行 循环 结束的时间戳
    print('耗时时间为:{}, 进程号为:{}'.format(end_time, os.getpid()))  # 获取耗时与进程号

执行结果如下图:

Python语法学习之进程的创建与常用方法详解

OKK!接下来进入我们今天要学习的主题。

将 work_for_first() 函数创建一个新的子进程去执行。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print('\'work_for_first\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print('\'work_for_second\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 获取执行 循环 之前的时间戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因为我们传入的函数没有参数所以 args 可以不写
    work_for_first_process.start()
    work_for_second()
    end_time = time.time() - start_time     # 获取执行 循环 结束的时间戳
    print('耗时时间为:{}, 进程号为:{}'.format(end_time, os.getpid()))  # 获取耗时与进程号

执行结果如下图:

Python语法学习之进程的创建与常用方法详解

因为我们针对 work_for_first() 函数创建一个新的子进程去执行,所以我们的耗时变为了 5秒。那么如果我们将 work_for_second() 函数也创建一个新的子进程去执行,耗时又会是多少呢?我们接着往下看。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print('\'work_for_first\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print('\'work_for_second\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 获取执行 循环 之前的时间戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因为我们传入的函数没有参数所以 args 可以不写
    work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    work_for_second_process.start()
    end_time = time.time() - start_time     # 获取执行 循环 结束的时间戳
    print('耗时时间为:{}, 进程号为:{}'.format(end_time, os.getpid()))  # 获取耗时与进程号

执行结果如下图:

Python语法学习之进程的创建与常用方法详解

PS:从脚本中执行入口的 main 函数可以看出 work_for_first() 函数 与 work_for_second() 函数 分别都由各自的子进程来执行,主进程实际执行的 只有 23行、29行、30行代码,所以从耗时来看,主进程实际上只执行了 0.026 秒。

这里再思考一个问题,如果是每一个子进程都单独的通过 .start 去启动,那么在子进程很多的情况下,启动的确实会有一些慢了。这个时候我们就可以通过 for 循环的方式去启动子进程。方式如下:

for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()

join 函数

同样的也会存在着这样一种情况,我们希望子进程运行结束之后再去执行我们的主进程,这时候我们就会使用到 join 函数 。

这里我们就利用上文的 进程 for循环同时启动两个子进程,然后我们再在下一个 for循环 执行 join 函数,我们看看会发生什么。

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print('\'work_for_first\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print('\'work_for_second\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 获取执行 循环 之前的时间戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因为我们传入的函数没有参数所以 args 可以不写
    # work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    # work_for_second_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.join()

    end_time = time.time() - start_time     # 获取执行 循环 结束的时间戳
    print('耗时时间为:{}, 进程号为:{}'.format(end_time, os.getpid()))  # 获取耗时与进程号

执行结果如下图:

Python语法学习之进程的创建与常用方法详解

kill 函数 与 is_alive 函数

接下来我们再尝试一个场景,利用 for 循环,我们同时启动 work_for_first() 函数 与 work_for_second() 函数 的子进程。然后我们再在另一个 for 循环中,将 work_for_second() 函数 的子进程 kill 掉,然后判断两个子进程的存活状态。

示例脚本如下:

# coding:utf-8


import time
import os
import multiprocessing


def work_for_first():

    for i in range(5):
        print('\'work_for_first\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


def work_for_second():
    for i in range(5):
        print('\'work_for_second\' 函数的循环值:{},进程号为:{}'.format(i, os.getpid()))
        time.sleep(1)


if __name__ == '__main__':
    start_time = time.time()    # 获取执行 循环 之前的时间戳
    work_for_first_process = multiprocessing.Process(target=work_for_first)     # 因为我们传入的函数没有参数所以 args 可以不写
    # work_for_first_process.start()

    work_for_second_process = multiprocessing.Process(target=work_for_second)
    # work_for_second_process.start()

    for sun_process in (work_for_first_process, work_for_second_process):
        sun_process.start()
        time.sleep(1)   # 休眠一秒是为了 work_for_second_process 子进程 至少能够运行一次


    for sun_process in (work_for_first_process, work_for_second_process):
        work_for_second_process.kill()
        if work_for_first_process.is_alive():
            print('\'work_for_first_process\' 子进程当前存活状态为:True')
        elif not work_for_second_process.is_alive():
            print('\'work_for_second_process\' 子进程当前存活状态为:False')

        sun_process.join()

    end_time = time.time() - start_time     # 获取执行 循环 结束的时间戳
    print('耗时时间为:{}, 进程号为:{}'.format(end_time, os.getpid()))  # 获取耗时与进程号

运行结果如下:

Python语法学习之进程的创建与常用方法详解

进程的相关问题

通过学习多进程的创建、启动,我们可以充分的体会到进程给我们带来的好处。它可以使我们的脚本程序执行时间进行缩短,从而提高工作效率。

然而多进程也有一些问题:

  • 通过进程模块执行的函数无法获取返回值,即便这个函数拥有 return 关键字也无法获取到,这也是我们进程的弊端。
  • 多个进程同时修改文件可能会出现错误。
  • 进程数量太多可能会造成资源不足、甚至死机等情况。

关于进程的这些问题,其实也并不是不能解决。在后续更新的 进程间的通信 、进程池与进程锁 的章节我们再进行详细的介绍。

到此这篇关于Python语法学习之进程的创建与常用方法详解的文章就介绍到这了,更多相关Python 进程创建内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python 列表(List)操作方法详解
Mar 11 Python
Python内置函数之filter map reduce介绍
Nov 30 Python
Python运算符重载用法实例分析
Jun 01 Python
Python利用递归和walk()遍历目录文件的方法示例
Jul 14 Python
Python操作mongodb数据库进行模糊查询操作示例
Jun 09 Python
Python实现简单层次聚类算法以及可视化
Mar 18 Python
Django中如何使用sass的方法步骤
Jul 09 Python
python与C、C++混编的四种方式(小结)
Jul 15 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
python实现二分查找算法
Sep 18 Python
python BeautifulSoup库的安装与使用
Dec 17 Python
Python 详解通过Scrapy框架实现爬取百度新冠疫情数据流程
Nov 11 Python
基于PyQt5制作一个群发邮件工具
Python&Matlab实现樱花的绘制
Python OpenCV形态学运算示例详解
4种方法python批量修改替换列表中元素
Apr 07 #Python
Python+OpenCV实现图片中的圆形检测
Python中文分词库jieba(结巴分词)详细使用介绍
基于Python实现对比Exce的工具
Apr 07 #Python
You might like
将PHP作为Shell脚本语言使用
2006/10/09 PHP
PHP+DBM的同学录程序(4)
2006/10/09 PHP
php ss7.5的数据调用 (笔记)
2010/03/08 PHP
php实现网页缓存的工具类分享
2015/07/14 PHP
php实现当前页面点击下载文件的实例代码
2016/11/16 PHP
PHP编辑器PhpStrom运行缓慢问题
2017/02/21 PHP
Javascript模板技术
2007/04/27 Javascript
推荐20家国外的脚本下载网站
2011/04/28 Javascript
读jQuery之十二 删除事件核心方法
2011/07/31 Javascript
jQuery Ajax 仿AjaxPro.Utility.RegisterTypeForAjax辅助方法
2011/09/27 Javascript
jquery动态分页效果堪比时光网
2014/09/25 Javascript
一分钟理解js闭包
2016/05/04 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
2016/07/04 Javascript
AngularJS中的API(接口)简单实现
2016/07/28 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
vue模板语法-插值详解
2017/03/06 Javascript
单行 JS 实现移动端金钱格式的输入规则
2017/05/22 Javascript
Javascript 一些需要注意的细节(必看篇)
2017/07/08 Javascript
jquery拖拽自动排序插件使用方法详解
2020/07/20 jQuery
17道题让你彻底理解JS中的类型转换
2019/08/08 Javascript
javascript实现左右缓动动画函数
2020/11/25 Javascript
详解vue3中组件的非兼容变更
2021/03/03 Vue.js
想学python 这5本书籍你必看!
2018/12/11 Python
python 画二维、三维点之间的线段实现方法
2019/07/07 Python
详解Python中Pyyaml模块的使用
2020/10/08 Python
Python+OpenCV图像处理——实现轮廓发现
2020/10/23 Python
八一建军节感言
2014/02/28 职场文书
培训协议书范本
2014/04/22 职场文书
南京市纪委监察局整改方案
2014/09/16 职场文书
教师学习八项规定六项禁令思想汇报
2014/09/27 职场文书
工作失职检讨书(精华篇)
2014/10/15 职场文书
现货白银电话营销话术
2015/05/29 职场文书
入党群众意见范文
2015/06/02 职场文书
五年级语文教学反思
2016/03/03 职场文书
python爬虫之selenium库的安装及使用教程
2021/05/23 Python
mysql 索引合并的使用
2021/08/30 MySQL