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中zip()函数用法实例教程
Jul 31 Python
Python实现将n个点均匀地分布在球面上的方法
Mar 12 Python
Python正则表达式匹配HTML页面编码
Apr 08 Python
教你用Type Hint提高Python程序开发效率
Aug 08 Python
定制FileField中的上传文件名称实例
Aug 23 Python
python实现简易云音乐播放器
Jan 04 Python
通过 Django Pagination 实现简单分页功能
Nov 11 Python
Python for循环搭配else常见问题解决
Feb 11 Python
Python类和实例的属性机制原理详解
Mar 21 Python
详解python百行有效代码实现汉诺塔小游戏(简约版)
Oct 30 Python
python实现学生信息管理系统(精简版)
Nov 27 Python
Django中的DateTimeField和DateField实现
Feb 24 Python
基于PyQt5制作一个群发邮件工具
Python&Matlab实现樱花的绘制
Python OpenCV形态学运算示例详解
4种方法python批量修改替换列表中元素
Apr 07 #Python
Python+OpenCV实现图片中的圆形检测
Python中文分词库jieba(结巴分词)详细使用介绍
基于Python实现对比Exce的工具
Apr 07 #Python
You might like
利用递归把多维数组转为一维数组的函数
2006/10/09 PHP
php实现对象克隆的方法
2015/06/20 PHP
PHP实现文字写入图片功能
2019/02/18 PHP
PHP生成随机密码4种方法及性能对比
2020/12/11 PHP
imagettftext() 失效,不起作用
2021/03/09 PHP
JS 常用校验函数
2009/03/26 Javascript
JS backgroundImage控制
2009/05/19 Javascript
ExtJs纵坐标值重复问题的解决方法
2014/02/27 Javascript
node.js中的events.EventEmitter.listenerCount方法使用说明
2014/12/08 Javascript
PHP实现的各种中文编码转换类分享
2015/01/23 Javascript
JavaScript阻止浏览器返回按钮的方法
2015/03/18 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
jQuery使用zTree插件实现树形菜单和异步加载
2016/02/25 Javascript
整理关于Bootstrap列表组的慕课笔记
2017/03/29 Javascript
vue使用drag与drop实现拖拽的示例代码
2017/09/07 Javascript
Vue 框架之键盘事件、健值修饰符、双向数据绑定
2018/11/14 Javascript
webpack打包多页面的方法
2018/11/30 Javascript
vue与bootstrap实现简单用户信息添加删除功能
2019/02/15 Javascript
了解javascript中let和var及const关键字的区别
2019/05/24 Javascript
jquery html添加元素/删除元素操作实例详解
2020/05/20 jQuery
vue中路由跳转不计入history的操作
2020/09/21 Javascript
python中MySQLdb模块用法实例
2014/11/10 Python
Python使用Scrapy爬取妹子图
2015/05/28 Python
mac安装scrapy并创建项目的实例讲解
2018/06/13 Python
numpy中矩阵合并的实例
2018/06/15 Python
程序员的七夕用30行代码让Python化身表白神器
2019/08/07 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
2020/06/18 Python
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
银行会计业务的个人自我评价
2013/11/02 职场文书
外语系毕业生自荐信范文
2013/12/16 职场文书
2014年三万活动总结
2014/04/26 职场文书
危爆物品安全大检查大整治工作方案
2014/05/03 职场文书
安全先进个人材料
2014/12/29 职场文书
2015年党风建设工作总结
2015/04/29 职场文书
python实现简单聊天功能
2021/07/07 Python
TS 类型收窄教程示例详解
2022/09/23 Javascript