「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。
正式的Python专栏第75篇,同学站住,别错过这个从0开始的文章!
通过前篇文章的铺垫,我们了解到了进程的概念。
针对线程,我们可以使用ThreadPoolExecutor的submit方法提交一个任务,生成一个线程执行,接着获取future对象,对future对象的状态进行解析。
如果是要开启一个进程来执行呢?
这就是本篇想要分享的内容,进程池。
ProcessPoolExecutor
ProcessPoolExecutor跟ThreadPoolExecutoor非常像,这个是一个进程池
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/2/23 10:20 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷学委
# @XueWeiTag: CodingDemo
# @File : processexecutordemo2.py
# @Project : DeepDivePython
import os
import threading
import time
from concurrent.futures.process import ProcessPoolExecutor
from datetime import datetime
def do_something(args):
print("%s process - pid: %s - args %s -" % (datetime.now(), os.getpid(), args))
time.sleep(3)
return "end of process " + str(os.getpid())
if __name__ == "__main__":
with ProcessPoolExecutor() as executor:
print("学委demo进程 PID:", os.getpid())
print("executor:", executor)
executor.map(do_something, [("ExecutorDemo") ]*5)
以上代码可以把进程池启动。
下面是运行结果,可以看到创建的进程序号都不同了。而且看起来是连续的。
其实它们是一组子进程,隶属于父进程(PID:12666)
另外特别说明一下,进程池的创建操作 必须 在程序进入main入口后!(更多原因请阅读分享文章解析这个问题)
跟ThreadPoolExecutor类似,shutdown和map,submit等方法也都配套了。
submit 任务到进程池,然后获取子进程的处理结果
沿用上面的代码,我们把程序入口的代码改为以下内容:
if __name__ == "__main__":
with ProcessPoolExecutor() as executor:
print("学委demo进程 PID:", os.getpid())
print("executor:", executor)
future = executor.submit(do_something, ("ExecutorDemo"))
print("任务运行结果:", future.result())
轻松的获取到了子进程的返回了:
当然出于性能考虑,我们一般使用线程池即可。
毕竟进程是线程的容器,开辟新进程的开销是比线程池大得多的。
什么时候用进程池?
可以是调用其他脚本或者跨语言调用的时候,单独开辟子进程来管理,这样比用线程池更合适。
Python中有个py4j库,这个是用来在python虚拟机中调用java代码的,这样明显的跨进程交换,用进程池就挺好的。
本系列主要定位开发新手或者初学者,某些概念适量提点到,暂时分享到这。
而且现在还有协程这个概念,当然不在这个并发库内涉及,有机会再谈。
多进程这块后面会专门写一个分布式多进程的专栏。
喜欢Python的朋友,请关注学委的 Python基础专栏 or Python入门到精通大专栏
持续学习持续开发,我是雷学委!
编程很有趣,关键是把技术搞透彻讲明白。
欢迎关注微信,点赞支持收藏!