【问题标题】:Asyncio task creation with different accepted methods give different results使用不同接受的方法创建 Asyncio 任务会产生不同的结果
【发布时间】:2021-03-09 16:02:19
【问题描述】:

有以下代码:

import asyncio

async def mycoro(number: int):
    print(f"Starting {number}")
    await asyncio.sleep(1)
    print(f"Finishing {number}")
    return str(number)
 
c = mycoro(7)
# task = asyncio.ensure_future(c)
task = asyncio.create_task(c)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
loop.close()

为什么我得到 sys:1: RuntimeWarning: coroutine 'mycoro' was never waiting

同时:

import asyncio

async def mycoro(number: int):
    print(f"Starting {number}")
    await asyncio.sleep(1)
    print(f"Finishing {number}")
    return str(number)

c = mycoro(7)
task = asyncio.ensure_future(c)
# task = asyncio.create_task(c)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
loop.close()

按预期运行

如果

按照https://docs.python.org/3.9/library/asyncio-task.html#creating-tasks两种创建任务的方式:

task = asyncio.create_task(coro())
task = asyncio.ensure_future(coro())

被接受了吗?

*用python3.9运行

【问题讨论】:

    标签: python-3.x python-asyncio


    【解决方案1】:

    警告只是警告之前发生的错误的副作用,这是真正的问题:

    Traceback (most recent call last):
      File "/home/hniksic/Desktop/a.py", line 11, in <module>
        task = asyncio.create_task(c)
      File "/usr/lib/python3.8/asyncio/tasks.py", line 381, in create_task
        loop = events.get_running_loop()
    RuntimeError: no running event loop
    

    您不能在正在运行的事件循环之外调用asyncio.create_task();它被设计为从协程内部调用以向事件循环提交附加任务。这种设计的原因是提交任务到“当前”事件循环(由asyncio.get_event_loop() 返回的),就像ensure_future 所做的那样,与asyncio.run() 不兼容,asyncio.run() 总是会创建一个新的事件循环。换句话说,如果顶级的asyncio.create_task(c)c 提交到“当前”事件循环,那么asyncio.run(other_coroutine()) 将忽略c,因为它运行不同的事件循环。为避免混淆,asyncio.create_task() 需要从正在运行的事件循环内部调用。

    如果您想在使用run_until_complete() 运行之前在特定事件循环上创建任务,您可以改用loop.create_task(c)。进行该更改会消除错误。

    【讨论】:

    • 你听起来是对的,我的脑袋目前正在围绕这个 asyncio 旋转,所以我会阅读更多关于这个主题的内容,一旦我完全理解你在说什么,我会返回将其标记为已接受的答案。谢谢!
    • @CatHariss 如果您是 asyncio 初学者,请查看 asyncio.run() 并在顶层调用它。在程序的顶层,您不需要调用create_task() 或显式处理事件循环。许多教程仍然使用run_until_complete(),这是较旧的 asyncio API。
    猜你喜欢
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    相关资源
    最近更新 更多