zoukankan      html  css  js  c++  java
  • ✍16 asyncio异步IO

    asyncio 简单使用

    • Python3版本的新特性, 本质上是协程
    • 异步IO采用消息循环的模式, 重复 读取消息--处理消息 的过程
    • 也就是说异步IO模型 需要一个消息循环,在消息循环中,主线程不断地重复 “读取消息--处理消息”这一过程

    关键字

    • async : 定义一个协程
    • await : 用于挂起阻塞的异步调用接口(IO)
    await作用:控制运行流程,按顺序执行,即等待该函数运行完成,再继续往后执行
    

    ps : python 3.5中对原本协程方式做了改变

    # 原本协程@asyncio.coroutine装饰,使用yield from来驱动(后面演示)
    
    @asyncio.coroutine ---> async
    yield from ---> await
    

    测试 :

    • 未添加asyncio
    import time
    
    def hello():
        time.sleep(1)
    
    def run():
        for i in range(5):
            hello()
            print('Hello World:%s' % time.time())
    if __name__ == '__main__':
        run()
    
    '''
    Hello World:1627525626.5793433
    Hello World:1627525627.579919
    Hello World:1627525628.581251
    Hello World:1627525629.5832856
    Hello World:1627525630.5842235
    '''
    
    • 添加asyncio
    import time
    import asyncio
    
    
    # 定义异步函数
    async def hello():
        print('Hello World:%s' % time.time())
        # 必须使用await,不能使用yield from;如果是使用yield from ,需要采用@asyncio.coroutine相对应
        await asyncio.sleep(1)
        print('Hello wow World:%s' % time.time())
    
    
    def run():
        tasks = []
        for i in range(5):
            tasks.append(hello())
        loop.run_until_complete(asyncio.wait(tasks))
    
    
    loop = asyncio.get_event_loop()
    if __name__ == '__main__':
        run()
    
    '''
    Hello World:1627525656.033751
    Hello World:1627525656.0337813
    Hello World:1627525656.0337918
    Hello World:1627525656.0338
    Hello World:1627525656.033807
    (约1s)
    Hello wow World:1627525657.035745
    Hello wow World:1627525657.0357795
    Hello wow World:1627525657.0357869
    Hello wow World:1627525657.0357919
    Hello wow World:1627525657.0357978
    '''
    
    • 用法2(3.7版本的写法)
    import time
    import asyncio
    
    
    async def task():
        await asyncio.sleep(3)
    
    
    async def main():
        task_list = []
        for i in range(5):
            task_list.append(task())
        await asyncio.gather(*task_list)
    
    
    if __name__ == '__main__':
        start_time = time.time()
        asyncio.run(task())
        print(f"用时:{time.time() - start_time} s")
    

    其他几种用法:https://zhuanlan.zhihu.com/p/72887901

    事件循环 Eventloop 的使用

    • Eventloop 是asyncio应用的核心,把一些异步函数注册到这个事件循环上
    • 事件循环会循环执行这些函数,当执行到某个函数时,如果它正在等待I/O返回,如它正在进行网络请求,或者sleep操作,事件循环会暂停它的执行去执行其他的函数
    • 当某个函数完成I/O后会恢复,下次循环到它的时候继续执行
    • 因此,这些异步函数可以协同(Cooperative)运行:这就是事件循环的目标

    示例 :

    • 原来装饰器的写法
    import asyncio
    
    @asyncio.coroutine
    def hello():
        print("Hello world!")
        # 异步调用asyncio.sleep(2): 
        yield from asyncio.sleep(2)
        print("Hello again!")
    
    # 获取EventLoop:
    loop = asyncio.get_event_loop()
    # 执行coroutine
    loop.run_until_complete(hello())
    loop.close()
    
    • task封装多个协程任务
    import threading
    import asyncio
    
    
    @asyncio.coroutine
    def hello():
        print('Hello world! (%s)' % threading.currentThread())
        yield from asyncio.sleep(2)
        print('Hello again! (%s)' % threading.currentThread())
    
    
    loop = asyncio.get_event_loop()
    tasks = [hello(), hello(),hello()]
    # loop.run_until_complete(asyncio.wait(tasks))
    loop.run_until_complete(asyncio.gather(*tasks)) # *号打散的方式
    loop.close()
    '''
    Hello world! (<_MainThread(MainThread, started 140426122789376)>)
    Hello world! (<_MainThread(MainThread, started 140426122789376)>)
    Hello world! (<_MainThread(MainThread, started 140426122789376)>)
    (约2s)
    Hello again! (<_MainThread(MainThread, started 140426122789376)>)
    Hello again! (<_MainThread(MainThread, started 140426122789376)>)
    Hello again! (<_MainThread(MainThread, started 140426122789376)>)
    '''
    
  • 相关阅读:
    AC日记——红色的幻想乡 洛谷 P3801
    AC日记——Power收集 洛谷 P3800
    AC日记——妖梦拼木棒 洛谷 P3799
    AC日记——妖梦斩木棒 洛谷 P3797
    AC日记——小魔女帕琪 洛谷 P3802
    AC日记——双栈排序 洛谷 P1155
    AC日记——明明的烦恼 bzoj 1005
    AC日记——[HNOI2014]世界树 bzoj 3572
    AC日记——魔法森林 洛谷 P2387
    AC日记——【模板】点分治(聪聪可可) 洛谷 P2634
  • 原文地址:https://www.cnblogs.com/songhaixing/p/15604869.html
Copyright © 2011-2022 走看看