美文网首页
Python基于基于协程的异步HTTP请求实现:使用asynci

Python基于基于协程的异步HTTP请求实现:使用asynci

作者: 睡不醒的大橘 | 来源:发表于2020-05-24 20:17 被阅读0次

    代码实现

    先创建一个基于Flask的server

    from flask import Flask
    from time import sleep
    
    app = Flask(__name__)
    
    @app.route('/<name>')
    def hello_world(name):
        sleep(5)
        return f'Hello {name}!'
    
    if __name__ == '__main__':
        app.run()
    

    client使用asyncio 与 aiohttp进行异步HTTP请求

    async def fetch(session, url):
        async with session.get(url) as response:
            return await response.text()
    
    
    async def main(name_list):
        async with aiohttp.ClientSession() as session:
            tasks = [asyncio.ensure_future(fetch(session, f'http://127.0.0.1:5000/{name}')) for name in name_list]
            res = await asyncio.gather(*tasks)
            print(res)
    
    
    if __name__ == '__main__':
    
        loop = asyncio.get_event_loop()
        name_list = ['a', 'b', 'c']
    
        start = time.time()
        loop.run_until_complete(main(name_list))
        end = time.time()
    
        print('elapsed time = ' + str(end - start))
        loop.close()
    

    先运行server, 然后运行client,client的输出:

    ['Hello a!', 'Hello b!', 'Hello c!']
    elapsed time = 5.019996881484985
    

    可见三个http get请求是异步进行的。

    要解释以上的代码,首先介绍一下Python协程


    Python协程 (Coroutine)

    • 一个例子

    借用一篇博客中的例子:

    “假设有1个洗衣房,里面有10台洗衣机,有一个洗衣工在负责这10台洗衣机。那么洗衣房就相当于1个进程,洗衣工就相当1个线程。如果有10个洗衣工,就相当于10个线程,1个进程是可以开多线程的。这就是多线程!

    那么协程呢?先不急。大家都知道,洗衣机洗衣服是需要等待时间的,如果10个洗衣工,1人负责1台洗衣机,这样效率肯定会提高,但是不觉得浪费资源吗?明明1 个人能做的事,却要10个人来做。只是把衣服放进去,打开开关,就没事做了,等衣服洗好再拿出来就可以了。就算很多人来洗衣服,1个人也足以应付了,开好第一台洗衣机,在等待的时候去开第二台洗衣机,再开第三台,……直到有衣服洗好了,就回来把衣服取出来,接着再取另一台的(哪台洗好先就取哪台,所以协程是无序的)。这就是计算机的协程!洗衣机就是执行的方法。”

    • 协程的特点

    协程,又称微线程。协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行。

    协程很适合处理IO密集型程序的效率问题。协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,因此对于CPU密集型程序协程需要和多进程配合。


    asyncio关键字

    asyncio是python3.4之后引入的协程模块。关于asyncio的一些关键字的说明:

    • event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数

    • coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

    • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态

    • future: 代表将来执行或没有执行的任务的结果。它和task上没有本质上的区别

    • async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,声明函数挂起的这个切换点,一般是一个耗时的IO操作。

    • run_until_complete方法:将协程包装成为了一个任务(task)对象. task对象是Future类的子类,保存了协程运行后的状态,用于未来获取协程的结果。run_until_complete会运行直到Future结束,返回Future的结果或者抛出exception。

    • asyncio.ensure_future(coroutine):用于创建task

    • asyncio.gather(*tasks):返回coroutine或者futures生成的结果。结果是一个list,顺序和输入的顺序一致,与返回结果的顺序无关。

    详细语法可参考官网:https://docs.python.org/3/library/asyncio-task.html#coroutines


    aiohttp

    aiohttp是一个基于asyncio的异步HTTP client和server, 在python3.5之后加入

    详细的语法可以参考官网:https://docs.aiohttp.org/en/stable/index.html

    相关文章

      网友评论

          本文标题:Python基于基于协程的异步HTTP请求实现:使用asynci

          本文链接:https://www.haomeiwen.com/subject/nszjahtx.html