Python的进程及进程池详解
作者:程序员-夏天 发布时间:2021-05-18 08:51:46
进程
进程是操作系统分配资源的基本单元,是程序隔离的边界。
进程和程序
程序只是一组指令的集合,它本身没有任何运行的含义,它是静态的。
进程程序的执行实例,是动态的,有自己的生命周期,有创建有撤销,存在是暂时的。
进程和程序不是一一对应的,一个程序可以对应多个进程,一个进程也可以执行一个或者多个程序。
我们可以这样理解:编写完的代码,没有运行时称为程序,正在运行的代码,会启动一个(或多个)进程。
进程的状态
在我们的操作系统⼯作时,任务数往往⼤于cpu核心数,即⼀定有⼀些任务正在执⾏,⽽另外⼀些任务在等待cpu,因此导致了进程有不同的状态。
就绪状态:已满⾜运⾏条件,等待cpu执⾏
执⾏状态:cpu正在执⾏
等待状态:等待某些条件满⾜,比如⼀个程序sleep了,此时就处于等待状态
Python中的进程
在Python中,进程是通过multiprocessing多进程模块来创建的,multiprocessing模块提供了⼀个Process类来创建进程对象。
创建⼦进程
Process语法结构:
Process(group, target, name, args, kwargs)
group
:指定进程组,⼤多数情况下⽤不到target
:表示调用对象,即子进程要执行的任务name
:子进程的名称,可以不设定args
:给target指定的函数传递的参数,以元组的⽅式传递kwargs
:给target指定的函数传递命名参数
Process常用方法
p.start()
启动进程,并调用该子进程中的p.run()方法p.join(timeout)
:主进程等待⼦进程执⾏结束再结束,timeout是可选的超时时间is_alive()
:判断进程⼦进程是否还存活p.run()
进程启动时运行的方法,正是它去调用target指定的函数p.terminate()
⽴即终⽌⼦进程
Process创建的实例对象的常⽤属性
name
:当前进程的别名,默认为Process-N,N为从1开始递增的整数
pid
:当前进程的pid(进程号)
import multiprocessing
import os
import time
def work(name):
print("子进程work正在运行......")
time.sleep(0.5)
print(name)
# 获取进程的名称
print("子进程name", multiprocessing.current_process())
# 获取进程的pid
print("子进程pid", multiprocessing.current_process().pid, os.getpid())
# 获取父进程的pid
print("父进程pid", os.getppid())
print("子进程运行结束......")
if __name__ == '__main__':
print("主进程启动")
# 获取进程的名称
print("主进程name", multiprocessing.current_process())
# 获取进程的pid
print("主进程pid", multiprocessing.current_process().pid, os.getpid())
# 创建进程
p = multiprocessing.Process(group=None, target=work, args=("tigeriaf", ))
# 启动进程
p.start()
print("主进程结束")
通过上述代码我们发现,multiprocessing.Process
帮我们创建一个子进程,并且成功运行,但是我们发现,在子进程还没执行完的时候主进程就已经死了,那么这个子进程在主进程结束后就是一个孤儿进程,那么我们可以让主进程等待子进程结束后再结束吗?答案是可以的。 那就是通过p.join(),join()的作用是让主进程等子进程执行完再退出。
import multiprocessing
import os
import time
def work(name):
print("子进程work正在运行......")
time.sleep(0.5)
print(name)
# 获取进程的名称
print("子进程name", multiprocessing.current_process())
# 获取进程的pid
print("子进程pid", multiprocessing.current_process().pid, os.getpid())
# 获取父进程的pid
print("父进程pid", os.getppid())
print("子进程运行结束......")
if __name__ == '__main__':
print("主进程启动")
# 获取进程的名称
print("主进程name", multiprocessing.current_process())
# 获取进程的pid
print("主进程pid", multiprocessing.current_process().pid, os.getpid())
# 创建进程
p = multiprocessing.Process(group=None, target=work, args=("tigeriaf", ))
# 启动进程
p.start()
p.join()
print("主进程结束")
运行结果:
可以看出,主进程是在子进程结束后才结束的。
全局变量问题
全局变量在多个进程中不共享,进程之间的数据是独立的,默认情况下互不影响。
import multiprocessing
# 定义全局变量
num = 99
def work1():
print("work1正在运行......")
global num # 在函数内部声明使⽤全局变量num
num = num + 1 # 对num值进⾏+1
print("work1 num = {}".format(num))
def work2():
print("work2正在运行......")
print("work2 num = {}".format(num))
if __name__ == '__main__':
# 创建进程p1
p1 = multiprocessing.Process(group=None, target=work1)
# 启动进程p1
p1.start()
# 创建进程p2
p2 = multiprocessing.Process(group=None, target=work2)
# 启动进程p2
p2.start()
运行结果:
从运⾏结果可以看出,work1()函数对全局变量num的修改,在work2中并没有获取到,⽽还是原来的99,所以,进程之间是不够共享变量的。
守护进程
上面说到,可以使用p.join()让主进程等待子进程结束后再结束,那么可不可以让子进程在主进程结束的时候就结束呢?答案是肯定的。 我们可以使用p.daemon = True或者p2.terminate()进行设置:
import multiprocessing
import time
def work1():
print("work1正在运行......")
time.sleep(4)
print("work1运行完毕")
def work2():
print("work2正在运行......")
time.sleep(10)
print("work2运行完毕")
if __name__ == '__main__':
# 创建进程p1
p1 = multiprocessing.Process(group=None, target=work1)
# 启动进程p1
p1.start()
# 创建进程p2
p2 = multiprocessing.Process(group=None, target=work2)
# 设置p2守护主进程
# 第⼀种⽅式
# p2.daemon = True 在start()之前设置,不然会抛异常
# 启动进程p2
p2.start()
time.sleep(2)
print("主进程运行完毕!")
# 第⼆种⽅式
p2.terminate()
执行结果如下:
由于p2设置了守护主进程,所以主进程运行完毕后,p2子进程也随之结束,work2任务停止,而work1继续运行至结束。
进程池
当需要创建的⼦进程数量不多时, 可以直接利⽤multiprocessing.Process
动态生成多个进程, 但如果要创建很多进程时,⼿动创建的话⼯作量会非常大,此时就可以⽤到multiprocessing
模块提供的Pool去创建一个进程池。
multiprocessing.Pool常⽤函数:
apply_async(func, args, kwds)
:使⽤⾮阻塞⽅式调⽤func(任务并⾏执⾏),args为传递给func的参数列表,kwds为传递给func的关键字参数列表apply(func, args, kwds)
:使⽤阻塞⽅式调⽤func,必须等待上⼀个进程执行完任务后才能执⾏下⼀个进程,了解即可,几乎不用close()
:关闭Pool,使其不再接受新的任务terminate()
:不管任务是否完成,⽴即终⽌join()
:主进程阻塞,等待⼦进程的退出,必须在close或terminate之后使⽤
初始化Pool时,可以指定⼀个最⼤进程数,当有新的任务提交到Pool中时,如果进程池还没有满,那么就会创建⼀个新的进程⽤来执⾏该任务,但如果进程池已满(池中的进程数已经达到指定的最⼤值),那么该任务就会等待,直到池中有进程结束才会创建新的进程来执⾏。
from multiprocessing import Pool
import time
def work(i):
print("work'{}'执行中......".format(i), multiprocessing.current_process().name, multiprocessing.current_process().pid)
time.sleep(2)
print("work'{}'执行完毕......".format(i))
if __name__ == '__main__':
# 创建进程池
# Pool(3) 表示创建容量为3个进程的进程池
pool = Pool(3)
for i in range(10):
# 利⽤进程池同步执⾏work任务,进程池中的进程会等待上⼀个进程执行完任务后才能执⾏下⼀个进程
# pool.apply(work, (i, ))
# 使⽤异步⽅式执⾏work任务
pool.apply_async(work, (i, ))
# 进程池关闭之后不再接受新的请求
pool.close()
# 等待po中所有子进程结束,必须放在close()后面, 如果使⽤异步⽅式执⾏work任务,主线程不再等待⼦线程执⾏完毕再退出!
pool.join()
执行结果为:
从结果我们可以看出,只有3个子进程在执行任务,此处我们使用的是异步⽅式(pool.apply_async(work, (i, )))
执⾏work任务,如果是以同步方式(pool.apply(work, (i, )))
执行,进程池中的进程会等待上⼀个进程执行完任务后才能执⾏下⼀个进程。
来源:https://blog.csdn.net/weixin_50097774/article/details/121428457


猜你喜欢
- 1. 连接对象操作数据库之前,首先要建立数据库连接。有下面几个方法进行连接。>>>import cx_Oracle>
- ansible 简介ansible 是什么?ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、
- 0. 前言无论在工作中,还是学习中,都会出现这样子的需求,对某张表进行了排序(按时间排序也好,其他字段排序也罢),然后获取前x行的数据,由于
- Node.js版本管理工具。Git地址:https://github.com/nvm-sh/nvm安装nvmMac OS:如果已经安装了no
- 详解 Python 读写XML文件的实例Python 生成XML文件from xml.dom import minidom# 生成XML文件
- 在做数据库修改或删除操作中,可能会导致数据错误,甚至数据库奔溃,而有效的定时备份能很好地保护数据库。本篇文章主要讲述Navicat for
- 基本信息程序包名称:基于.net开发的遵循web标准的个人站点程序包下载开发者主页:www.ceocio.net软件大小:1.84mb安装环
- 最近在重新看vue3的rfcs,发现一个细节,原话如下:props that start with on are handled as v-
- 一、抓取全部评论吾的这篇文章,有 1022 次评论,一条条看,吾看不过来,于是想到 Python 词云,提取关键词,倒也是一桩趣
- 现在只有山东、北京、上海等发达地区有考Python的这个举动,其他地区暂时还没有。首先,Python类似于c++,Python是一种面向对象
- 一、引入必要文件下载地址:(https://github.com/nghuuphuoc/bootstrapvalidator/archive
- 本文实例为大家分享了python使用Matplotlib绘制分段函数的具体代码,供大家参考,具体内容如下环境Python3Mac OS代码#
- 书 名:细节决定交互设计的成败国际书号:ISBN 978-7-121-08232-0作 &nb
- 众所周知,python是写爬虫的利器,今天作者用python写一个小爬虫爬下一个段子网站的众多段子。目标段子网站为“http://ishuo
- 普通滑动验证以http://admin.emaotai.cn/login.aspx为例这类验证码只需要我们将滑块拖动指定位置,处理起来比较简
- 本文实例讲述了Vue插槽原理与用法。分享给大家供大家参考,具体如下:1 插槽内容Vue 实现了一套内容分发的 API,这套 API 基于当前
- 前言面对计算密集型的任务,除了多进程,就是分布式计算,如何用 Python 实现分布式计算呢?今天分享一个很简单的方法,那就是借助于 Ray
- 这篇文章主要介绍了js简单的分页器插件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参
- 我看blog里,还有很多地方都引用过我写的这个类,转了不少,但自己一直也没发表过,这次正式发表一下。在蓝色理想中有人不懂怎么用,我在baid
- 正在编写的程序用的很多Windows下的操作,查了很多资料。看到剪切板的操作时,想起以前想要做的一个小程序,当时也没做,现在正好顺手写完。功