Python3.7 高级编程之 async/await asyncio 事件循环的使用

什么是事件循环:
事件循环是每个 asyncio 应用的核心。 事件循环会运行异步任务和回调,执行网络 IO 操作,以及运行子进程。
说简单点就是由于python是单线程的 程序在执行中会将所有任务放到队列中去逐一执行,当发现阻塞时就去执行其他任务,知道程序结束。
应用开发者通常应当使用高层级的 asyncio 函数,例如 asyncio.run(),应当很少有必要引用循环对象或调用其方法。

主要方法介绍:
asyncio.get_running_loop():返回当前 OS 线程中正在运行的事件循环。如果没有正在运行的事件循环则会引发 RuntimeError。 此函数只能由协程或回调来调用。
asyncio.get_event_loop():获取当前事件循环。如果当前OS线程中没有设置当前事件循环,则OS线程是主线程,并且尚未调用set_event_loop(),asyncio将创建一个新的事件循环并将其设置为当前事件循环。
由于此函数具有相当复杂的行为(特别是在使用了自定义事件循环策略的时候),更推荐在协程和回调中使用 get_running_loop() 函数而非 get_event_loop()。
应该考虑使用 asyncio.run() 函数而非使用低层级函数来手动创建和关闭事件循环。
asyncio.set_event_loop(loop):将 loop 设置为当前 OS 线程的当前事件循环。
asyncio.new_event_loop():创建一个新的事件循环。

使用事件循环创建并运行task任务

import asyncio, time

async def set_after(delay, value):
    await asyncio.sleep(delay)
    print(value)

async def main():
    loop = asyncio.get_running_loop() # 返回当前 系统 线程中正在运行的事件循环。在这里使用它是用为 asyncio.run(main()) 已经启动了事件循环,因此get_running_loop() 可以获得
    # 在事件循环中创建任务
    task1 = loop.create_task(set_after(2, '... Hello'))
    task2 = loop.create_task(set_after(3, '... world'))
    # 执行任务
    await task1
    await task2

if __name__ == '__main__':
    start_time = time.time()
    # 方式一 直接使用高层函数run() 方法,简单粗暴,不需要自己管理太多东西
    # asyncio.run(main())
    # 方式二 使用底层的函数 可以更加细致的控制事件循环
    loop = asyncio.get_event_loop() # 如果这里替换成get_running_loop() 则会报错,原因是当前系统中并没有在运行的事件循环。
    task1 = loop.create_task(set_after(2, '... Hello'))
    task2 = loop.create_task(set_after(3, '... world'))
    loop.run_until_complete(asyncio.wait([task1, task2]))
    print('耗时:', time.time() - start_time)

使用事件循环来使用Future对象

import asyncio, time


async def set_after(fut, delay, value):
    # await asyncio.sleep(delay) # 当使用Future时 没有await 依然可以运行,但是要set_result,否则会阻塞。使用Future还可以设置返回值,实际中还是看个人应用了。
    fut.set_result(value)
    print(value)

async def say(delay, value):
    await asyncio.sleep(delay)
    print(value)

async def main():
    loop = asyncio.get_running_loop() # 返回当前 系统 线程中正在运行的事件循环。
    # 在事件循环中创建Futrue
    fut1 = loop.create_future()
    fut2 = loop.create_future()
    # 为Future创建任务
    task1 = loop.create_task(set_after(fut1, 2, '你好'))
    task2 = loop.create_task(set_after(fut2, 3, 'Python'))
    # await task1
    # await task2
    # 可以替换上面语句
    await fut1
    await fut2
    print('得到返回值:', fut1.result(), fut2.result())


if __name__ == '__main__':
    start_time = time.time()
    # 方式一 直接使用高层函数run() 方法,简单粗暴,不需要自己管理太多东西
    # asyncio.run(main())
    # 方式二 使用底层的函数 可以更加细致的控制事件循环
    loop = asyncio.get_event_loop() # 如果这里替换成get_running_loop() 则会报错,原因是当前系统中并没有在运行的事件循环。
    future1 = asyncio.ensure_future(say(2, '... Hello'))
    future2 = asyncio.ensure_future(say(3, '... world'))
    # loop.run_until_complete(asyncio.wait([future1, future2]))
    loop.run_until_complete(asyncio.gather(*[future1, future2]))  # 可以替换上面的语句
    print('耗时:', time.time() - start_time)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章