Python语法学习之进程的创建与常用方法详解
作者:渴望力量的哈士奇 发布时间:2023-11-08 11:23:34
该章节我们来学习一下在 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())) # 获取耗时与进程号
执行结果如下图:
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())) # 获取耗时与进程号
执行结果如下图:
因为我们针对 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())) # 获取耗时与进程号
执行结果如下图:
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())) # 获取耗时与进程号
执行结果如下图:
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())) # 获取耗时与进程号
运行结果如下:
进程的相关问题
通过学习多进程的创建、启动,我们可以充分的体会到进程给我们带来的好处。它可以使我们的脚本程序执行时间进行缩短,从而提高工作效率。
然而多进程也有一些问题:
通过进程模块执行的函数无法获取返回值,即便这个函数拥有 return 关键字也无法获取到,这也是我们进程的弊端。
多个进程同时修改文件可能会出现错误。
进程数量太多可能会造成资源不足、甚至死机等情况。
关于进程的这些问题,其实也并不是不能解决。在后续更新的 进程间的通信 、进程池与进程锁 的章节我们再进行详细的介绍。
来源:https://blog.csdn.net/weixin_42250835/article/details/124030773


猜你喜欢
- 当我们花费大量的精力训练完网络,下次预测数据时不想再(有时也不必再)训练一次时,这时候torch.save(),torch.load()就要
- window对象是JavaScript浏览器对象模型中的顶层对象,包含多个常用方法和属性: 1 打开新窗口 window.open(page
- 平时我们获取事件对象一般写法如下:function getEvent(event) { return e
- tell()方法返回的文件内的文件读/写指针的当前位置。语法以下是tell()方法的语法:fileObject.tell()参数
- 目录前言场景模拟总结前言近期多次聊到sql_mode的话题,也是多次遇到相关问题,今天就趁热打铁,再给大家带来一个sql_mode的案例分享
- 在触屏设备上,一些比较基础的手势都需要通过对 touch 事件进行二次封装才能实现。zepto 是移动端上使用率比较高的一个类库,但是其 t
- 1.安装PHP脚本运行环境yum install -y php php-mysql2.加载官方percona模板[root@cat /]#
- 1、if条件选择# coding:utf-8num = 23if num>2:print("dayu")if nu
- 本文实例讲述了python异常处理、自定义异常、断言原理与用法。分享给大家供大家参考,具体如下:什么是异常:当程序遭遇某些非正常问题的时候就
- 早就想用一个系列的文章来写AJAX,让自己头到尾理一遍,更好的掌握基础知识(昨天的面试受打击了,基础知识很重要).要是写的好,也许也可以帮助
- 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-Conq
- 本文实例讲述了python自动化测试之setUp与tearDown的用法,分享给大家供大家参考。具体如下:实例代码如下:class Roma
- 学习golang不久,在定义全局变量的时候遇见了坑。写个小例子,增强记忆。错误版本var p intfunc main() { p, err
- 在使用python编程过程中,我们往往需要借助字典来提高编程效率。同时为了调试方便,我们希望将某些变量保存为中间文件。例如,在协同过滤算法中
- 一、Python 下载Python是运行的环境,必不可少,如果你是Linux系统的话,不用安装,自带了Python。首先我们打开浏览器搜索P
- 层次聚类算法顾名思义,层次聚类就是一层一层的进行聚类,可以由上向下把大的类别(cluster)分割,叫作分裂法;也可以由下向上对小的类别进行
- 你懂的,手工翻译表定义到go结构体是很枯燥的。so,用xorm搞定。go get github.com/go-xorm/cmd/xorm安装
- 实现制作抽奖程序,需要认知到我们可以看到一般抽奖程序界面上是有很多按钮的,比如中奖区域,按键开始区域等等,所以我们先要设置界面,然后把这些按
- 本文实例讲述了Python自定义线程池实现方法。分享给大家供大家参考,具体如下:关于python的多线程,由与GIL的存在被广大群主所诟病,
- 本文实例为大家分享了python遍历文件目录、批量处理同类文件的具体代码,供大家参考,具体内容如下目录操作1、获取当前目录import os