像线程一样管理进程的Python multiprocessing库
作者:李元静 发布时间:2023-06-01 15:37:39
一、创建一个进程
要创建一个进程,最简单的方式是用一个目标函数实例化一个Process对象,然后与threading一样调用start()函数让它工作。示例如下:
import multiprocessing
def worker():
for i in range(3):
print(i)
if __name__=="__main__":
p = multiprocessing.Process(target=worker)
p.start()
运行之后,效果如下:
需要注意的是,multiprocessing库在Windows创建进程必须在if __name__=="__main__":中,这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果直接创建就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 __name__ 不是 __main__ ,就不会递归运行了。
二、设置进程名
在threading线程中,我们可以通过其参数name设置线程名,同样的我们也可以通过name参数设置其进程的名字。示例如下:
import multiprocessing
import time
def worker():
print(multiprocessing.current_process().name, "start")
time.sleep(2)
print(multiprocessing.current_process().name, "end")
if __name__ == "__main__":
p1 = multiprocessing.Process(name='p1', target=worker)
p2 = multiprocessing.Process(name='p2', target=worker)
p3 = multiprocessing.Process(name='p3', target=worker)
p1.start()
p2.start()
p3.start()
运行之后,效果如下:
三、守护进程
和线程一样,在所有子进程没有退出之前,主程序是不会退出的。有时候,我们可能需要启动一个后台进程,它可以一直运行而不阻塞主程序退出。
要标志一个守护进程,可以将其添加第3个参数daemon,设置为True。默认值为False,不作为守护进程。示例如下:
import multiprocessing
import time
def worker():
print(multiprocessing.current_process().name, "start")
time.sleep(1)
print(multiprocessing.current_process().name, "end")
def worker2():
print(multiprocessing.current_process().name, "start")
time.sleep(2)
print(multiprocessing.current_process().name, "end")
if __name__ == "__main__":
p1 = multiprocessing.Process(name='p1', target=worker)
p2 = multiprocessing.Process(name='p2', target=worker2, daemon=True)
p3 = multiprocessing.Process(name='p3', target=worker2, daemon=True)
p1.start()
p2.start()
p3.start()
运行之后,效果如下:
p2,p3为守护进程,但p1不是所以执行1秒之后,就退出主程序了,也就没有打印p2p3的内容。但是其依旧在执行中,直到执行完成。
四、join()
同样的,如果你期望强制等待一个守护进程的结束,可以增加join()函数。还是上面的代码,示例如下:
import multiprocessing
import time
def worker():
print(multiprocessing.current_process().name, "start")
time.sleep(1)
print(multiprocessing.current_process().name, "end")
def worker2():
print(multiprocessing.current_process().name, "start")
time.sleep(2)
print(multiprocessing.current_process().name, "end")
if __name__ == "__main__":
p1 = multiprocessing.Process(name='p1', target=worker)
p2 = multiprocessing.Process(name='p2', target=worker2, daemon=True)
p3 = multiprocessing.Process(name='p3', target=worker2, daemon=True)
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
运行之后,和设置进程名的运行结果一样,这里不在展示。唯一与守护进程代码的区别就是最后三行join()函数代码。当然,也可以像线程一样,给join()函数传入一个时间,超过这个时间,主进程不再等待。
五、强制结束进程
如果一个进程已经挂起或者不小心进入了死锁状态,那么这个时候,我们往往会强制的结束进程。对一个进程对象调用terminate()会结束子进程。示例如下:
import multiprocessing
import time
def worker():
print(multiprocessing.current_process().name, "start")
time.sleep(5)
print(multiprocessing.current_process().name, "end")
if __name__ == "__main__":
p1 = multiprocessing.Process(name='p1', target=worker)
p1.start()
print("是否还在运行", p1.is_alive())
p1.terminate()
print("是否还在运行", p1.is_alive())
p1.join()
print("是否还在运行", p1.is_alive())
运行之后,输出如下:
终止进程后要使用join()函数等待进程的退出。使进程管理代码有足够的时间更新对象的状态,以反应进程已经终止。
六、进程退出状态码
进程退出时,生成的状态码可以通过exitcode属性访问。下表就是其状态码的取值范围以及其意义:
退出码 | 含义 |
0 | 未生成任何错误 |
>0 | 进程有一个错误,并以该错误码退出 |
<0 | 进程以一个-1*exitcodde信号结束 |
测试如下:
import multiprocessing
import time
def worker():
print(multiprocessing.current_process().name, "start")
time.sleep(5)
print(multiprocessing.current_process().name, "end")
if __name__ == "__main__":
p1 = multiprocessing.Process(name='p1', target=worker)
p2 = multiprocessing.Process(name='p2', target=worker)
p1.start()
p2.start()
print("是否还在运行", p1.is_alive())
p1.terminate()
print("是否还在运行", p1.is_alive())
print(p1.exitcode)
p1.join()
print("是否还在运行", p1.is_alive())
print(p1.exitcode)
time.sleep(5.5)
print(p2.exitcode)
运行之后,效果如下:
可以看到,强制退出的进程状态码为负数,正常退出的进程状态码为0。
七、日志
调试并发问题时,如果能够访问multiprocessing所提供对象的内部状态,那么这会很有用。在实际的项目中,我们可以使用一个方便的模块级函数启用日志记录,它使用logging建立一个日志记录器对象,并增加一个处理器,使日志消息被发送到标准错误通道。
示例如下:
import multiprocessing
import logging
import sys
def worker():
print("运行工作进程")
sys.stdout.flush()
if __name__ == "__main__":
multiprocessing.log_to_stderr(logging.DEBUG)
p1 = multiprocessing.Process(name='p1', target=worker)
p1.start()
p1.join()
运行之后,效果如下:
八、派生进程
与线程一样,我们可以自定义进程,而不必只是传入一个函数进行进程的创建。
创建的进程的方式也是派生自进程类即可。示例如下:
import multiprocessing
class WorkerProcess(multiprocessing.Process):
def run(self):
print(self.name)
return
if __name__ == "__main__":
for i in range(5):
p = WorkerProcess()
p.start()
p.join()
运行之后,效果如下:
multiprocessing库的进程知识与threading一样长,因为本篇的内容已经够长了,剩下的知识我们将在下一篇博文中接着讲解。
来源:https://liyuanjinglyj.blog.csdn.net/article/details/116859021


猜你喜欢
- 我想大多数的人在编写ASP程序的时候,都碰到过类似的错误信息: Error Number ->
- 他们都可以把 x 变成一个布尔类型的值:>>> x = 123>>> not not xTrue>
- 如下所示:# coding=gbkfrom PIL import Imageimport numpy as np# import scipy
- 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具。在计算机中,是协调多个进程或县城并发访问某一资源的一种机制。在数据库当中,除了传统的
- 一、维数的变形1. 一维数组转二维数组以及同维变换import numpy as nparr_1d = np.arange(12)# 使用
- 提到分发请求,相信大多数人首先会想到Nginx,Nginx作为一种多功能服务器,不仅提供了反向代理隐藏主机ip的能力,还拥有简单的缓存加速功
- 本文为大家分享了pygame游戏之旅的第12篇,供大家参考,具体内容如下实现点击功能:click = pygame.mouse.get_pr
- 如下所示:import loggingimport logging.configlogging.config.fileConfig(path
- 目录分页后添加删除功能实现模态框编辑内容完整代码笔记利用layui框架实现分页:layui实现完整表格分页:自己实现分页:# name: m
- 1、plotly库的相关介绍1)相关说明plotly是一个基于javascript的绘图库,plotly绘图种类丰富,效果美观;易于保存与分
- 最近好多伙伴说,我用vue做的项目本地是可以的,但部署到服务器遇到好多问题:资源找不到,直接访问index.html页面空白,刷新当前路由4
- 代码如下:<% sql="select * from serr where
- 前几天安装Python的时候没有装上pip工具,所以只能现在手动安装了。首先,访问https://bootstrap.pypa.io/get
- 自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓厚的兴趣,在工作和学习中也
- 一、旧式的字符串格式化% 操作符参考以下示例:>>> name = "Eric">>>
- 代码和代码运行的结果:代码:import itertools as itswords="rot123"a=its.pro
- 前言python画图,如果用英文显示基本没有问题,但是中文可能会有乱码或者不显示的情况。经过个人的测试,下图中“横轴&a
- 执行sql 语句,中间没有用到临时表提示服务器: 消息 9002,级别 17,状态 2,行 1数据库 'tempdb' 的日
- 前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理基本开发环境 Python
- 下面展示一下非瀑布流的item布局情况,每个item的高度都是一样的,所以 他的index就是左右左右,position所对应的itemVi