• asynico异步编程高层级API


    一、前言

      之前写过 asynico 异步编程的文章,写那篇博客的时候 python 最新官方版本是3.6+。几个月后发布了 python3.7,这次版本更新对 asynico 改动挺大的,官方推出了一套 高层级的API,其实就是封装了原来那套低层级的API。

      python 通过协程来实现异步编程,因此我们首先来了解下协程。

    二、协程

    1)协程通过 async/await 语法进行声明,使用 asyncio.run() 函数执行协程,此函数会运行传入的协程,负责管理 asyncio 事件循环,终结异步生成器,并关闭线程池。如下代码所示:

    import asyncio,datetime
    
    async def main():
        print(datetime.datetime.now())
        await asyncio.sleep(1)
        print(datetime.datetime.now())
    
    if __name__ =='__main__':
        asyncio.run(main())

    2)如果一个对象想在 await 语句中使用,那么它必须是 可等待 对象。许多 asyncio API 都被设计为接受可等待对象,可等待 对象有三种主要类型:协程、任务 和 Future

    • 协程

      Python中的协程也是可等待对象,因此可被 await。如 price 协程方法:

    import asyncio
    
    
    async def price(x,y):
        return x*y
    
    async def main():
        P = await price(1,2)
        print(P)
    
    if __name__ =='__main__':
        asyncio.run(main())
    • 任务

      当协程通过 asyncio.create_task()方法 被封装成一个任务,并自行调度执行任务,该方法 python 3.7版本被加入,低版本使用 asyncio.ensure_future() 。

    import asyncio
    
    async
    def price(x,y): return x*y async def main(): task = asyncio.create_task(price(1,2)) P = await task print(P) if __name__ =='__main__': asyncio.run(main())
    • Future

      Future 是一种特殊的 低层级 可等待对象,表示一个异步操作的最终结果。官网 不建议在应用层级的代码中创建 Future 对象,因此没有深入了解。

    三、并发任务

      线程在遇到IO等待时,会被阻塞,并 交出CPU控制权,换句话来说由 系统控制线程切换。协程遇到IO等待时,则由 程序控制,不会被阻塞,也 不会交出CPU控制权,而是直接执行下一个事务。所以协程在处理IO密集型任务时,资源开销小,效率极高,优于多线程。

      使用 asyncio.gather(*aws) 并发运行协程,如果所有可等待对象都成功完成,结果将是一个由所有返回值聚合而成的列表。结果值的顺序与 aws 中可等待对象的顺序一致。

    import asyncio,datetime
    
    async def price(x,y):
        await asyncio.sleep(1)
        print(datetime.datetime.now())
        return x*y
    
    async def main():
        P = await asyncio.gather(price(1,2),
                                 price(2,4))
        print(P)
    
    if __name__ =='__main__':
        asyncio.run(main())
    
    
    #输出
    #2021-11-17 20:11:17.180417
    #2021-11-17 20:11:17.180417
    #[2, 8]

    低层级 API 和 高层级 API 代码对比 

    • 低层级 API 代码如下是 python 3.7 以下版本 实现并发的代码:
    import time
    import asyncio
    from aiohttp import ClientSession
    
    tasks = []
    url = "https://www.baidu.com/{}"
    async def hello(url):
        async with ClientSession() as session:
            async with session.get(url) as response:
    #            print(response)
                print('Hello World:%s' % time.time())
                return await response.read()
    
    def main():
        for i in range(5):
            task = asyncio.ensure_future(hello(url.format(i)))
            tasks.append(task)
        result = loop.run_until_complete(asyncio.gather(*tasks))
        print(result)
    
    if __name__ == '__main__':
        loop = asyncio.get_event_loop()
        main()
    
    
    # 输出
    '''
    Hello World:1637152588.856801
    Hello World:1637152588.856801
    Hello World:1637152588.8577979
    Hello World:1637152588.8619971
    Hello World:1637152588.864993
    [b'<!DOCTYPE HTML PUBLIC "- ...
    '''
    • 高层级 API 代码,省去了显式的定义事件循环等,看上去更加简洁、容易理解:
    import time
    import asyncio
    from aiohttp import ClientSession
    
    tasks = []
    url = "https://www.baidu.com/{}"
    async def hello(url):
        async with ClientSession() as session:
            async with session.get(url) as response:
                print('Hello World:%s' % time.time())
                return await response.read()
    
    async def main():
        hello_list = [hello(url.format(i)) for i in range(5)]
        P = await asyncio.gather(*hello_list)
        print(P)
    
    if __name__ == '__main__':
        asyncio.run(main())
    
    
    # 输出
    '''
    Hello World:1637152648.7986703
    Hello World:1637152648.8146682
    Hello World:1637152648.8151577
    Hello World:1637152648.8450766
    Hello World:1637152648.8491611
    [b'<!DOCTYPE HTML PUBLIC "-/...
    '''

     asynico 还处于不断完善阶段,版本升级后都会有些小的变动,请及时查阅文档:asynico官方文档

     

  • 相关阅读:
    一文搞懂 deconvolution、transposed convolution、sub-­pixel or fractional convolution
    Knative 实战:三步走!基于 Knative Serverless 技术实现一个短网址服务
    使用Bookinfo应用测试Kuma服务网格
    数学——Euler方法求解微分方程详解(python3)
    深度学习之卷积神经网络CNN及tensorflow代码实现示例
    如何让cxgrid既能充满又能根据内容进行宽度调整?
    cxgrid过滤使用心得
    DevExpress控件cxGrid实现多列模糊匹配输入的完美解决方案
    sqlserver的触发器练习实例
    SQL Server 创建触发器(trigger)
  • 原文地址:https://www.cnblogs.com/shenh/p/15401891.html
Copyright © 2020-2023  润新知