Python 并发库之 ProcessPoolExecutor代码展示

1,384 阅读2分钟

「这是我参与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)

屏幕快照 2022-02-26 下午10.39.03.png

另外特别说明一下,进程池的创建操作 必须 在程序进入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())

轻松的获取到了子进程的返回了:

屏幕快照 2022-02-26 下午10.47.47.png

当然出于性能考虑,我们一般使用线程池即可。

毕竟进程是线程的容器,开辟新进程的开销是比线程池大得多的。

什么时候用进程池?

可以是调用其他脚本或者跨语言调用的时候,单独开辟子进程来管理,这样比用线程池更合适。

Python中有个py4j库,这个是用来在python虚拟机中调用java代码的,这样明显的跨进程交换,用进程池就挺好的。

本系列主要定位开发新手或者初学者,某些概念适量提点到,暂时分享到这。

而且现在还有协程这个概念,当然不在这个并发库内涉及,有机会再谈。

多进程这块后面会专门写一个分布式多进程的专栏。

喜欢Python的朋友,请关注学委的 Python基础专栏 or Python入门到精通大专栏

持续学习持续开发,我是雷学委!
编程很有趣,关键是把技术搞透彻讲明白。
欢迎关注微信,点赞支持收藏!