由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信)

这篇具有很好参考价值的文章主要介绍了由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

从底层到第三方库,全面讲解python的异步编程。这节讲述的是python的多线程实现,纯干货,无概念,代码实例讲解。

本系列有6章左右,点击头像或者专栏查看更多内容,陆续更新,欢迎关注。

部分资料来源及参考链接:
https://www.bilibili.com/video/BV1Li4y1j7RY/

multiprocessing(多进程)

现在让我们初步进入多进程,这个就是python的多进程包,是自带的,简单示例:

import multiprocessing#进程包
import time

def start():
   time.sleep(2)#让程序沉睡 2 秒
   print(multiprocessing.current_process().name)#打印进程名字
   print(multiprocessing.current_process().pid)#打印pid
   print(multiprocessing.current_process().is_alive())#打印进程是否活着

if __name__ == "__main__":
   print('程序开始')
   p = multiprocessing.Process(target = start)#只用写函数名  不要加括号
   p.start()#开始
   p.join()#堵塞
   print('程序结束')

此时,并不是一个进程打开多个线程,而是多个进程,所以每次执行有不同的pid。

结果如下:
由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信),python,python,开发语言,多进程,进程池,异步编程

进程通信

本身进程是无法通信的,借助别的数据结构,就可以实现进程通信了,一般是栈和队列,就像这样:

from multiprocessing import Process,Queue

def write(q):#放入队列

    print('加入队列成功:{}'.format(Process.pid))#打印进程pid

    for i in range(10):# 0~9
        print('往队列放入:{}'.format(i))
        q.put(i)#放入

def read(q):#读取队列

    print('加入队列成功:{}'.format(Process.pid))#打印进程pid

    while True:#一有东西 就马上读取
        value = q.get()#读取
        print('获取队列中的东西:{}'.format(value))


if __name__ == "__main__":
    
    #由于Python的多进程默认无法进行通信   因为是并发执行的
    #所以要借助别的数据结构 
    #一般用栈 或者 队列
    q = Queue()#实例化Queue   队列
    pw = Process(target = write,args =(q,))#创建写入进程
    pr = Process(target = read,args = (q,))#创建读取进程
    pw.start()#启动写入
    pr.start()#启动读取

    pw.join()#堵塞读取

python当中实现了栈和队列,非常方便,如果你运行上述代码,你会发现程序没有结束,读取进程它还在反复读取。这其实就和golang中的管道类似。此处可以先做了解。

进程池

可以使用map方法批量提交目标

import multiprocessing

def index_pool(data):
    res = data * data
    return res

if __name__ == "__main__":

    data =  list(range(100))#100个任务 
    pool = multiprocessing.Pool(processes = 4)#进程池大小为4

    pool_out_puts = pool.map(index_pool,data)#一次性提交大量任务
    # pool_out_puts = pool.apply(index_pool,args=(10,))#一个个提交
    pool.close()#关闭进程  不再创建进程
    pool.join()#堵塞进程
    
    print('Pool    {}'.format(pool_out_puts))

运行结果:
由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信),python,python,开发语言,多进程,进程池,异步编程

你会发现执行速度非常快

为什么进程池这么快呢?

这就是与多线程的区别,每个进程是独立的,不会受到GIL锁的控制,速度非常快

异步进程池

上述的例子中,进程是同步执行的,如何写出异步的效果呢?

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor,as_completed
import time

number_list = [1,2,3,4,5,6,7,8,9,10]

def add_number(data):#这个函数  只能消耗CPU资源  没啥意义

    item = count(data)
    return item

def count(number):#单纯计算  随便写

    for i in range(0,5000000):
        i = i + 1

    return i * number

if __name__ == "__main__":
    
    start_time = time.time()#程序启动时间

    with ProcessPoolExecutor(max_workers = 5) as t:# max_workers参数为 你要开多少个进程

        for item in number_list:#提交任务 
            t.submit(add_number,item)

        # reqs = [t.submit(add_number,item) for item in number_list]#提交任务 简洁写法
        # for req in as_completed(reqs):# 转成 可迭代对象
        #     print(req.result())#打印信息

    print('程序总耗时:{}'.format(time.time() - start_time))

由于没有GIL锁的限制,执行会非常快。

进程池和异步进程池的区别是什么呢?

在Python中,进程池(Process Pool)和异步进程池(Asyncio Process Pool)是用于并行处理任务的两种不同的机制。

进程池(Process Pool):
进程池是通过multiprocessing模块提供的一种机制,它允许你创建一组预先初始化的进程,用于执行任务。你可以将任务提交给进程池,进程池会自动分配可用的进程来执行任务。进程池可以通过Pool类来创建。
进程池适用于CPU密集型任务,可以充分利用多核处理器的并行性。它通过创建多个进程来同时执行任务,每个进程都有自己的Python解释器和GIL,因此可以实现真正的并行执行。进程池在处理大量计算密集型任务时通常具有较好的性能。

异步进程池(Asyncio Process Pool):
异步进程池是通过concurrent.futures和asyncio模块提供的一种机制,它允许在异步环境中并行处理任务。异步进程池是建立在异步编程的基础上,可以在单个线程中同时执行多个任务。
异步进程池适用于IO密集型任务,如网络请求、文件读写等。它利用异步编程的特性,通过在任务之间进行切换来提高效率,避免了线程切换的开销。异步进程池在处理大量IO密集型任务时通常具有较好的性能。

进程池和线程池处理IO密集型的任务都很快吗?

异步线程池和异步进程池的主要区别在于线程池使用的是线程,而进程池使用的是进程。

线程池:在Python中,线程是由操作系统管理的,多个线程共享同一进程的内存空间,因此线程之间的切换开销较小。线程池适用于IO密集型任务,如网络请求、文件读写等,因为在这些任务中,大部分时间都是在等待IO操作完成,线程可以在等待期间切换执行其他任务,提高效率。

进程池:进程是由操作系统管理的,每个进程都有独立的内存空间,进程之间切换的开销较大。进程池适用于CPU密集型任务,如数据处理、图像处理等,因为这些任务需要大量的计算资源,多个进程可以并行执行,提高效率。

无论是线程池还是进程池,在处理IO密集型任务时都可以提高效率。但对于CPU密集型任务,由于Python的全局解释器锁(GIL)的存在,多线程并不能真正实现并行执行,因此在这种情况下使用进程池更为合适。如果需要同时处理大量IO密集型和CPU密集型任务,可以结合使用线程池和进程池来充分利用多核资源。

为什么不直接用进程池呢?

进程会特别占用内存,能够使用线程池的场景,还是使用线程池更好。

用实例解释进程池和异步进程池的区别

以网络爬虫为例:
当使用进程池和异步进程池来实现网络爬虫项目时,它们的处理逻辑和性能表现有一些区别。

使用进程池的处理逻辑如下:

  1. 创建一个进程池对象,设置进程数为10。
  2. 将待爬取的URL列表分成若干个子任务,每个子任务包含多个URL。
  3. 使用进程池的map()方法,将子任务提交给进程池。
  4. 进程池会自动将子任务分配给空闲的进程进行处理,每个进程负责处理一个子任务。
  5. 当所有子任务都完成时,进程池会返回结果,可以通过返回的结果来获取爬取的数据。

使用异步进程池的处理逻辑如下:

  1. 创建一个异步进程池对象,设置进程数为10。
  2. 将待爬取的URL列表分成若干个子任务,每个子任务包含多个URL。
  3. 使用异步进程池的submit()方法,将每个子任务提交给异步进程池。
  4. 异步进程池会立即返回一个Future对象,表示该子任务的执行状态。
  5. 可以通过Future对象的result()方法来获取子任务的结果,如果子任务还未完成,result()方法会阻塞等待直到结果可用。
  6. 可以使用concurrent.futures.as_completed()函数来迭代Future对象,获取已完成的子任务结果。

在性能方面,异步进程池通常比进程池更快。这是因为异步进程池可以同时执行多个任务,不需要等待一个任务完成后才能执行下一个任务,从而提高了效率。而进程池则需要按顺序逐个处理任务,无法并行执行。对于IO密集型的任务,异步进程池的性能提升更为明显,因为它可以充分利用CPU等待IO的时间来执行其他任务。文章来源地址https://www.toymoban.com/news/detail-770258.html

到了这里,关于由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 由浅入深掌握各种 Python 进程间通信方式(建议收藏)

    转载本文请注明 CSDN 链接处: https://blog.csdn.net/captain5339/article/details/129099833 Python代码效率由于受制于GIL全局锁限制,多线程不能利用多核CPU来加速,而 多进程 方式却可以绕过GIL限制, 发挥多CPU加速的优势,达到提高程序的性能的目的。 然而进程间通信却是不得不考虑的问题。

    2024年02月02日
    浏览(48)
  • Python+大数据-大学生精通Python从由浅入深(Python基础篇)

    看到这位 头发浓密 大叔了吗!1989年,为了打发圣诞节假期,龟叔(吉多·范·罗苏姆)开始写Python语言的编译器 。 1991年 ,第一个Python编译器诞生 Python这个名字,来自龟叔所挚爱的电视剧Monty Python’s Flying Circus (蒙蒂·蟒蛇的飞行马戏团) 我们为什么要学习这一项语言,Pytho

    2024年02月13日
    浏览(42)
  • Docker由浅入深(一)

    容器化技术介绍 介绍容器化之前,我们得先知道,为什么会出现容器化,容器化之前都经历了什么 物理机时代 部署非常慢 成功很高 浪费资源 难于扩展与迁移 受制于硬件 虚拟化时代 在同一个物理机上安装多个虚拟机,每个虚拟机安装操作系统和应用, 虚拟机之间物理资源

    2024年02月03日
    浏览(49)
  • 由浅入深了解HashMap源码

           由经典面试题引入,讲解一下HashMap的底层数据结构?这个面试题你当然可以只答,HashMap底层的数据结构是由(数组+链表+红黑树)实现的,但是显然面试官不太满意这个答案,毕竟这里有一个坑需要你去填,那就是在回答HashMap的底层数据结构时需要考虑JDK的版本,因

    2023年04月13日
    浏览(42)
  • 【个人笔记】由浅入深分析 ClickHouse

    项目中不少地方使用到ClickHouse,就对它做了一个相对深入一点的了解和研究。并对各种知识点及整理过程中的一些理解心得进行了汇总并分享出来,希望对其他同学能有帮助。 本文主要讲解ClickHouse的特点、读写过程、存储形式、索引、引擎、物化视图等特性。 适合 入门和

    2024年01月20日
    浏览(43)
  • React - redux 使用(由浅入深)

    中文文档: http://www.redux.org.cn/ 英文文档: https://redux.js.org/ Github: https://github.com/reactjs/redux 可直接参照 目录十 进行使用 react-redux redux 是一个专门用于做状态管理的JS库(不是react插件库)。 它可以用在 react, angular, vue 等项目中, 但基本与 react 配合使用。 作用: 集中式管理 re

    2024年02月07日
    浏览(49)
  • 由浅入深Netty代码调优

    序列化,反序列化主要用在消息正文的转换上 序列化时,需要将 Java 对象变为要传输的数据(可以是 byte[],或 json 等,最终都需要变成 byte[]) 反序列化时,需要将传入的正文数据还原成 Java 对象,便于处理 目前的代码仅支持 Java 自带的序列化,反序列化机制,核心代码如

    2024年02月05日
    浏览(42)
  • 【由浅入深学习MySQL】之索引进阶

    本系列为:MySQL数据库详解,为千锋资深教学老师独家创作 致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【关注】持续追更~ 文末有本文重点总结,技术类问题,也欢迎大家和我们沟通交流! 从今天开始本系列

    2024年02月05日
    浏览(42)
  • 由浅入深理解C#中的事件

    本文较长,给大家提供了目录,可以直接看自己感兴趣的部分。 前面介绍了C#中的委托,事件的很多部分都与委托类似。实际上,事件就像是专门用于某种特殊用途的简单委托,事件包含了一个私有的委托,如下图所示: 有关事件的私有委托需要了解的重要事项如下: 1、事

    2024年02月03日
    浏览(39)
  • 手拉手Vue组件由浅入深

    组件 (Component) 是 Vue.js 最强大的功能之一,它是html、css、js等的一个聚合体,封装性和隔离性非常强。 组件化开发:     1、将一个具备完整功能的项目的一部分分割多处使用     2、加快项目的进度     3、可以进行项目的复用 组件注册分为:全局注册和局部注册 目录

    2024年01月18日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包