asyncio.wait

发布于 2022-09-12 00:50:12 字数 855 浏览 30 评论 0

import threading
import asyncio

async def hello():
    print('Hello world! (%s)' % threading.currentThread())
    await asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

以上代码中 loop.run_until_complete(asyncio.wait(tasks)) 为什么不能直接写成 asyncio.wait(tasks)
python doc对asyncio.wait的解释为:

并发运行 aws 指定的 可等待对象 并阻塞线程直到满足 return_when 指定的条件。

我的理解是,如果wait能够实现并发运行的效果,那么就没必要用事件循环了,不知道这么理解哪里错了。
如果直接写的话会有以下报错:

yield_from.py:11: RuntimeWarning: coroutine 'wait' was never awaited
  asyncio.wait(tasks)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
sys:1: RuntimeWarning: coroutine 'hello' was never awaited

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

煮茶煮酒煮时光 2022-09-19 00:50:12

简单的原因是asyncio.wait的返回类型是一个coroutine,而不是运行后面的tasks,不精确来说,wait的实现是:

async def wait(tasks): # 省略里其他参数
    # "并行"运行 tasks
    # await 所有 tasks
    return

所以应该是await asyncio.wait(tasks),但当前脚本不是一个async的,所以这里并不能这样写。

具体来说,所有协程都是运行在一个线程里,不像多线程那样,由操作系统强制线程暂停执行(挂起)。在协程里,是需要协程主动交出执行权限(可以是协程执行完,或是awaityeild等等)。如果你写了如下代码,那么hello的第二个print永远得不得执行:

#!/usr/local/bin/python3.7
import threading
import asyncio
import time

async def hello():
    print('Hello world! (%s)' % threading.currentThread(), flush=True)
    await asyncio.sleep(2)
    print('Hello again! (%s)' % threading.currentThread(), flush=True)
async def run_for_ever():
    await asyncio.sleep(1)
    while True:
        time.sleep(1)

loop = asyncio.get_event_loop()
tasks = [run_for_ever(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

当协程主动交出执行权之后,就需要有管理器管理下一步执行哪一个“就绪”的协程。python并没有提供一个这样的“管理器”,所以就需要我们自行创建一个这样的管理器--事件循环:当一个协程交出执行权之后,事件循环获得执行权,由事件循环决定下一步继续执行那个协程。所以我们需要“手动“(模块)创建事件循环,然后把需要的协程加入到相应的循环(告诉管理器,你需要管理这个协程),最后还需要运行事件循环(把执行权交给”管理器“)。于是,asyncio提供了一个方法(run_until_complete)让我们尽量简单的实现上述步骤。

这也解释了为什么await只能写到async函数中——如果没有事件循环(“管理器”),当前执行权本协程应该交给谁?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文