python协程不一个一个运行?

问题描述 投票:0回答:1

我有一个以特定频率触发事件的函数,以及一个作为动作的协程任务。下面是我的实现(功能

wrapper
),但是它们似乎同时运行,发生了什么事?

import time
import asyncio
start = time.time()

def main(callback):
    for i in range(5):
        time.sleep(.5)
        callback()

async def sub_task():
    print("sub_task", time.time() - start)


#-----------------------
# below is what i do 
def wrapper():
    asyncio.create_task(sub_task())

main(wrapper)

# output: why don't they run at 0.5 sec interval?
#sub_task 2.57704758644104
#sub_task 2.57704758644104
#sub_task 2.57704758644104
#sub_task 2.5780487060546875
#sub_task 2.5780487060546875
python coroutine
1个回答
1
投票

您的代码有几处错误,很难解释所有这些,因此,我将向您展示执行您期望的代码,然后进行解释:

import time
import asyncio
from typing import Coroutine, Callable

START = time.time()

async def run_loop(callback: Callable[[], Coroutine]) -> None:
    for _ in range(5):
        await asyncio.sleep(0.5)
        await callback()

async def sub_task() -> None:
    print("sub_task", time.time() - START)

async def main() -> None:
    await run_loop(sub_task)

asyncio.run(main())
sub_task 0.5007944107055664
sub_task 1.0015990734100342
sub_task 1.5024292469024658
sub_task 2.003257989883423
sub_task 2.504088878631592

那么,这是如何运作的? 首先,我相信您知道您确实需要与当前配置异步运行所有这些。我假设 async-nes 出现在示例中未显示的部分中。 编辑:正如 Michael Butscher 指出的那样,这也解释了为什么您当前的代码会同时运行:在笔记本中,当您没有正在运行的事件循环并尝试添加它时,循环将最后运行,在阻塞代码完成。在我测试它的终端中,它根本不会运行。

那么,您没有在当前代码中运行异步循环。我认为这也只是因为您忘记将它添加到示例中。在这种情况下,我使用

asyncio.run
来启动循环并确保我们在示例的其余部分处于异步函数中。重要的是要注意
run_loop
也需要是一个异步函数:否则,它需要在每次要运行时创建自己的异步循环,阻塞其他一切。我想你还有其他异步的事情要做,所以,这个也需要是异步的。

然后,有几点需要注意: 首先,

time.sleep
一切, 也是异步代码。如果你不想让 sleep 阻塞当前异步函数之外的东西,你应该使用
await asyncio.sleep()

然后,在您的

create_task
中调用函数
sub_task
这将返回一个未来。你忘记的是,未来只能等待一次。如果你想多次等待一个
async
函数,你需要多次调用它。我试图通过类型注释使这一点更清楚。

我希望一切都解决了。 :-)

© www.soinside.com 2019 - 2024. All rights reserved.