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实现的金山快盘的签到程序
Jan 17 Python
零基础写python爬虫之抓取糗事百科代码分享
Nov 06 Python
简单介绍Ruby中的CGI编程
Apr 10 Python
Python中对象迭代与反迭代的技巧总结
Sep 17 Python
Python编程之变量赋值操作实例分析
Jul 24 Python
定制FileField中的上传文件名称实例
Aug 23 Python
Python编程之gui程序实现简单文件浏览器代码
Dec 08 Python
Python3爬虫全国地址信息
Jan 05 Python
10 分钟快速入门 Python3的教程
Jan 29 Python
关于pytorch中网络loss传播和参数更新的理解
Aug 20 Python
解决pytorch-yolov3 train 报错的问题
Feb 18 Python
python使用BeautifulSoup 解析HTML
Apr 24 Python
基于PyQt5制作一个群发邮件工具
Python&Matlab实现樱花的绘制
Python OpenCV形态学运算示例详解
4种方法python批量修改替换列表中元素
Apr 07 #Python
Python+OpenCV实现图片中的圆形检测
Python中文分词库jieba(结巴分词)详细使用介绍
基于Python实现对比Exce的工具
Apr 07 #Python
You might like
用PHP和ACCESS写聊天室(二)
2006/10/09 PHP
PHP连接MSSQL2008/2005数据库(SQLSRV)配置实例
2014/10/22 PHP
深入理解PHP中的empty和isset函数
2016/05/26 PHP
yii2中结合gridview如何使用modal弹窗实例代码详解
2016/06/12 PHP
JSON两种结构之对象和数组的理解
2016/07/19 PHP
浅谈PHP安全防护之Web攻击
2017/01/03 PHP
把字符串按照特定的字母顺序进行排序的js代码
2014/01/28 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
2014/02/26 Javascript
Jquery遍历select option和添加移除option的实现方法
2016/08/26 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
JavaScript获取URL中参数querystring的方法详解
2016/10/11 Javascript
Node.js包管理器Yarn的入门介绍与安装
2016/10/17 Javascript
概述一个页面从输入URL到页面加载完的过程
2016/12/16 Javascript
不使用 JS 匿名函数理由
2017/11/17 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
vue-cli3 karma单元测试的实现
2019/01/18 Javascript
原生js实现html手机端城市列表索引选择城市
2020/06/24 Javascript
JavaScript中reduce()的5个基本用法示例
2020/07/19 Javascript
[51:00]Secret vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
python实现从字典中删除元素的方法
2015/05/04 Python
python统计字母、空格、数字等字符个数的实例
2018/06/29 Python
对Python通过pypyodbc访问Access数据库的方法详解
2018/10/27 Python
在python中利用KNN实现对iris进行分类的方法
2018/12/11 Python
解决python写入带有中文的字符到文件错误的问题
2019/01/31 Python
基于python实现自动化办公学习笔记(CSV、word、Excel、PPT)
2019/08/06 Python
Python 单例设计模式用法实例分析
2019/09/23 Python
python等差数列求和公式前 100 项的和实例
2020/02/25 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
2020/05/13 Python
什么是python的函数体
2020/06/19 Python
python+django+selenium搭建简易自动化测试
2020/08/19 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
工程管理造价应届生求职信
2013/11/13 职场文书
中级会计职业生涯规划书
2014/03/01 职场文书
安全施工责任书
2014/08/25 职场文书
2014年防汛工作总结
2014/12/08 职场文书
2015年学生管理工作总结
2015/05/26 职场文书