Python多进程(一)进程及进程池
进程
进程是操作系统分配资源的基本单元,是程序隔离的边界。
进程和程序
程序只是一组指令的集合,它本身没有任何运行的含义,它是静态的。
进程程序的执行实例,是动态的,有自己的生命周期,有创建有撤销,存在是暂时的。
进程和程序不是一一对应的,一个程序可以对应多个进程,一个进程也可以执行一个或者多个程序。
我们可以这样理解:编写完的代码,没有运行时称为程序,正在运行的代码,会启动一个(或多个)进程。
进程的状态
在我们的操作系统⼯作时,任务数往往⼤于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 timedef work(name):print("子进程work正在运行......")time.sleep(0.5)print(name)# 获取进程的名称print("子进程name", multiprocessing.current_process())# 获取进程的pidprint("子进程pid", multiprocessing.current_process().pid, os.getpid())# 获取父进程的pidprint("父进程pid", os.getppid())print("子进程运行结束......")if __name__ == '__main__':print("主进程启动")# 获取进程的名称print("主进程name", multiprocessing.current_process())# 获取进程的pidprint("主进程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 timedef work(name):print("子进程work正在运行......")time.sleep(0.5)print(name)# 获取进程的名称print("子进程name", multiprocessing.current_process())# 获取进程的pidprint("子进程pid", multiprocessing.current_process().pid, os.getpid())# 获取父进程的pidprint("父进程pid", os.getppid())print("子进程运行结束......")if __name__ == '__main__':print("主进程启动")# 获取进程的名称print("主进程name", multiprocessing.current_process())# 获取进程的pidprint("主进程pid", multiprocessing.current_process().pid, os.getpid())# 创建进程p = multiprocessing.Process(group=None, target=work, args=("tigeriaf", ))# 启动进程p.start()p.join()print("主进程结束")
运行结果:
可以看出,主进程是在子进程结束后才结束的。
全局变量问题
全局变量在多个进程中不共享,进程之间的数据是独立的,默认情况下互不影响。
import multiprocessing# 定义全局变量
num = 99def work1():print("work1正在运行......")global num # 在函数内部声明使⽤全局变量numnum = num + 1 # 对num值进⾏+1print("work1 num = {}".format(num))def work2():print("work2正在运行......")print("work2 num = {}".format(num))if __name__ == '__main__':# 创建进程p1p1 = multiprocessing.Process(group=None, target=work1)# 启动进程p1p1.start()# 创建进程p2p2 = multiprocessing.Process(group=None, target=work2)# 启动进程p2p2.start()
运行结果:
从运⾏结果可以看出,work1()函数对全局变量num的修改,在work2中并没有获取到,⽽还是原来的99,所以,进程之间是不够共享变量的。
守护进程
上面说到,可以使用p.join()让主进程等待子进程结束后再结束,那么可不可以让子进程在主进程结束的时候就结束呢?答案是肯定的。 我们可以使用p.daemon = True或者p2.terminate()进行设置:
import multiprocessing
import timedef work1():print("work1正在运行......")time.sleep(4)print("work1运行完毕")def work2():print("work2正在运行......")time.sleep(10)print("work2运行完毕")if __name__ == '__main__':# 创建进程p1p1 = multiprocessing.Process(group=None, target=work1)# 启动进程p1p1.start()# 创建进程p2p2 = multiprocessing.Process(group=None, target=work2)# 设置p2守护主进程# 第⼀种⽅式# p2.daemon = True 在start()之前设置,不然会抛异常# 启动进程p2p2.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 timedef 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, )))执行,进程池中的进程会等待上⼀个进程执行完任务后才能执⾏下⼀个进程。
总结
本篇只介绍了什么是进程、进程与程序的关系、进程的创建与使用、创建进程池等,并没有介绍进程同步及进程通信等,下篇文章将会介绍。
Python多进程(一)进程及进程池相关推荐
- python多进程线程学习_python进程、线程的学习心得
什么是多线程竞争? 线程不是独立的,同一个进程里的线程,线程间的数据是共享的,多线程操作时,容易造成数据的混乱,线程不安全. 如何解决? 互斥锁. 好处:能够保证某段关键代码执行时,只有一个线程操作, ...
- python多进程通信manager_python中进程间数据通讯模块multiprocessing.Manager的介绍
本篇文章给大家带来的内容是关于python中进程间数据通讯模块multiprocessing.Manager的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目前开发中有遇到进程 ...
- python 多进程一篇学懂
目录 1.python多进程介绍 1.1 进程介绍 1.2 进程与线程的区别: 2.创建一个进程(Process类) 2.1 建立函数,直接创建进程 2. 2 通过类继承的方法创建进程 3.进程间的通 ...
- Python 多进程的进程池pool运行时报错:ValueError: Pool not running
本文仅供学习交流使用,如侵立删!demo下载见文末 Python 多进程的进程池pool运行时报错:ValueError: Pool not running def main(self, num):& ...
- Python多进程4 进程池——Pool
原文地址 学习来源 分类目录--多进程 是multiprocessing模块下的一个类,是一种创建多进程的更加简便的方式,可以更加方便的分配任务与传递参数. pool = mp.Pool(proces ...
- python 进程间同步_python之路29 -- 多进程与进程同步(进程锁、信号量、事件)与进程间的通讯(队列和管道、生产者与消费者模型)与进程池...
所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了.至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠 ...
- python 多进程并发(进程池)
前言 最近在处理大数据相关的东西,数据动辄上百万,还不能用 GPU 加速,于是开始动起了多进程的念头.众所周知,Python 的多线程是假的,不过好在开发者老大还是给我们留了一个活路,也就是进程池.这 ...
- python—多进程之进程池
一.进程池 1.进程池定义: 进程池:可以提供指定数量的进程给用户使用,即当有新的请求提交到进程池中时,如果池未满,则会创建一个新的进程用来执行该请求;反之,如果池中的进程数已经达到规定最大值,那么该 ...
- python 多进程共享变量manager_python 进程间共享数据 multiprocessing 通信问题 — Manager...
Python中进程间共享数据,处理基本的queue,pipe和value+array外,还提供了更高层次的封装.使用multiprocessing.Manager可以简单地使用这些高级接口. Mana ...
最新文章
- 在线项目管理软件leangoo 管理 技术支持
- generator自动生成mybatis配置和类信息
- python怎么重新开始_人人都是数据科学家从新开始用Python学习数据科学的完整教程P3...
- 谷歌市场上架aab安装包的各种坑
- UR驱动包安装过程及遇到问题的解决方案
- Web Services 详解
- 苹果 Mac 上不显示外置硬盘?9 个必须尝试的修复方法
- WinForm中TextBox的几个基本技巧
- bios sgx需要开启吗_Win10改Win7,UEFI改Legacy 启动,修改BIOS大全
- windriver linux创建工程
- 1.React 简介
- linux mint 使用软件管理器安装软件
- 微软的一道前端面试题
- 25 行 Python 代码实现人脸检测——OpenCV 技术教程
- 老树新芽 体验Visual Basic 9.0新功能
- C++ operator重载运算符详解
- matlab求解多自由度振动系统,【2017年整理】1-《机械振动基础》大作业,基于matlab的多自由度振动.doc...
- 100集华为HCIE安全培训视频教材整理 | PKI核心部分CA
- PAT | 1086 就不告诉你 (15分) 【测试点1、2】
- 智能镜柜原来这么好用,真后悔我家装晚了