✍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)>)
'''
posted @ 2021-11-25 20:55  给你骨质唱疏松  阅读(19)  评论(0编辑  收藏  举报