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 相关文章推荐
解决PyCharm中光标变粗的问题
Aug 05 Python
windows下python之mysqldb模块安装方法
Sep 07 Python
好的Python培训机构应该具备哪些条件
May 23 Python
python绘制直线的方法
Jun 30 Python
Python实现的json文件读取及中文乱码显示问题解决方法
Aug 06 Python
详解python Todo清单实战
Nov 01 Python
python3.6生成器yield用法实例分析
Aug 23 Python
python tornado修改log输出方式
Nov 18 Python
Python Celery多队列配置代码实例
Nov 22 Python
关于pytorch处理类别不平衡的问题
Dec 31 Python
python 基于pygame实现俄罗斯方块
Mar 02 Python
python中Tkinter 窗口之输入框和文本框的实现
Apr 12 Python
基于PyQt5制作一个群发邮件工具
Python&Matlab实现樱花的绘制
Python OpenCV形态学运算示例详解
4种方法python批量修改替换列表中元素
Apr 07 #Python
Python+OpenCV实现图片中的圆形检测
Python中文分词库jieba(结巴分词)详细使用介绍
基于Python实现对比Exce的工具
Apr 07 #Python
You might like
GD输出汉字的函数的分析
2006/10/09 PHP
透析PHP的配置文件php.ini
2006/10/09 PHP
PHP修改session_id示例代码
2014/01/08 PHP
thinkPHP框架实现类似java过滤器的简单方法示例
2018/09/05 PHP
laravel中Redis队列监听中断的分析
2020/09/14 PHP
ie下动态加态js文件的方法
2011/09/13 Javascript
web的各种前端打印方法之jquery打印插件jqprint实现网页打印
2013/01/09 Javascript
简略说明Javascript中的= =(等于)与= = =(全等于)区别
2013/04/16 Javascript
A标签中通过href和onclick传递的this对象实现思路
2013/04/19 Javascript
JavaScript字符串删除重复字符的方法
2015/12/25 Javascript
简单谈谈Vue 模板各类数据绑定
2016/09/25 Javascript
关于jQuery.ajax()的jsonp碰上post详解
2017/07/02 jQuery
利用node.js实现反向代理的方法详解
2017/07/24 Javascript
Node.JS段点续传:Nginx配置文件分段下载功能的实现方法
2018/03/12 Javascript
Vue 项目分环境打包的方法示例
2018/08/03 Javascript
微信小程序使用echarts获取数据并生成折线图
2019/10/16 Javascript
vue解决花括号数据绑定不成功的问题
2019/10/30 Javascript
js判断在哪个浏览器打开项目的方法
2020/01/21 Javascript
js实现有趣的倒计时效果
2021/01/19 Javascript
python类继承用法实例分析
2015/05/27 Python
Python读取properties配置文件操作示例
2018/03/29 Python
python计算两个矩形框重合百分比的实例
2018/11/07 Python
Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】
2019/06/18 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
使用tensorflow框架在Colab上跑通猫狗识别代码
2020/04/26 Python
Weekendesk意大利:探索多种引人入胜的周末主题
2016/10/14 全球购物
英国景点门票网站:attractiontix
2019/08/27 全球购物
别名指示符是什么
2012/10/08 面试题
敏捷开发的主要原则都有哪些
2015/04/26 面试题
请问软件开发中的设计模式你会使用哪些
2015/05/13 面试题
2015年音乐教研组工作总结
2015/07/22 职场文书
党员干部学法用法心得体会
2016/01/21 职场文书
JavaGUI模仿QQ聊天功能完整版
2021/07/04 Java/Android
Python中rapidjson参数校验实现
2021/07/25 Python
使用redis实现延迟通知功能(Redis过期键通知)
2021/09/04 Redis
Mysql存储过程、触发器、事件调度器使用入门指南
2022/01/22 MySQL