首页 > 其他 > 详细

认识协程异步IO

时间:2021-05-27 11:16:18      阅读:27      评论:0      收藏:0      [点我收藏+]

在执行某些IO密集型任务的时候,程序常常会因为等待 IO 而阻塞。为解决这一问题,可以考虑使用python中的协程异步。

从 Python 3.4 开始,Python 中加入了协程的概念,但这个版本的协程还是以生成器对象为基础的,在 Python 3.5 则增加了关键字async/await,使得协程的实现更加方便,本文中通过async/await 来实现协成。

python中使用协程最常用的库是asyncio,可以帮我们检测IO(只能是网络IO【HTTP连接就是网络IO操作】),实现应用程序级别的切换(异步IO)。

1、基本概念:

  • event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足条件发生的时候,就会调用对应的处理方法。可通过asyncio.get_event_loop()方法来生成。
  • coroutine:协程对象,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。这个类似于含有yield关键字的生成器函数,在调用时先返回一个生成器对象。
  • task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。可以通过asyncio.ensure_future(coroutine)方法生成,也可以通过event_loop.create_task(coroutine)方法生成。如果有多个任务,我们可以将多个任务添加到一个列表比如tasks中,并将tasks作为参数传入asyncio.wait(tasks)方法,然后将这个整体注册到事件循环中。
  • async/await :它是从 Python 3.5 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。await 后面的对象可以是以下3种格式---1)一个原生 coroutine 对象。2)一个由 types.coroutine() 修饰的生成器,这个生成器可以返回 coroutine 对象。3)一个包含__await方法的对象返回的一个迭代器。

2.aiohttp库

  要实现真正的异步,必须要使用支持异步操作的请求方式。aiohttp 是一个支持异步请求的库,利用它和 asyncio 配合我们可以非常方便地实现异步请求操作。

安装: pip3 install aiohttp 

官方文档链接为:https://aiohttp.readthedocs.io/

3、多任务协程

  • 利用flask实现一个慢速响应的服务器

    # coding:utf-8
    import time
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route(/)
    def index():
       time.sleep(3)
       return hello world
    
    if __name__ == __main__:
        app.run(threaded=True) #开启多线程模式

    该服务器3秒后才做出响应。

  • 多任务协程代码

    # coding:utf-8
    import asyncio
    import time
    import aiohttp
    
    
    start_time = time.time()
    async def request():
        url = "http://127.0.0.1:5000/"
        result = await get(url) #await将耗时等待的操作挂起,让出控制权
        print(result)
    
    
    async def get(url):
        session = aiohttp.ClientSession()
        response = await session.get(url)
        result = await response.read() #返回bytes类型
        # result = await response.text() #返回str类型
        await session.close()
        return result
    
    
    tasks = [asyncio.ensure_future(request()) for _ in range(5)] #创建5个task
    loop = asyncio.get_event_loop() #创建事件循环对象
    loop.run_until_complete(asyncio.wait(tasks)) #task列表传给 wait()方法并注册到事件循环中执行。
    end_time = time.time()
    print(花费时间:{}秒.format(end_time-start_time))

    执行结果:

    bhello world
    bhello world
    bhello world
    bhello world
    bhello world
    花费时间:3.0151724815368652秒

    运行时间在3秒左右,如果采用同步,则需要15秒左右,速度提升非常可观。尤其对于成百上千的任务来说,效果更为明显。

 

认识协程异步IO

原文:https://www.cnblogs.com/eliwang/p/14815596.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!