python 中的慢函数而非 运行 中的异步函数

Slow function in python not running asyncronously

我在 python 中有一个慢函数,我想 运行 异步。这个慢函数基本上是一个很长的循环,如下所示:



def slow(slowness):
    print(f"Slow loop {slowness}")
    for i in range(int(slowness * 1e8)):
        i
    print(f"Wait for loop {slowness} finished")


if __name__ == '__main__':

    slow(1)
    slow(0.5)
    slow(0.1)

我正在尝试 运行 异步版本,使用以下代码:

import asyncio

async def slow(slowness):
    print(f"Slow loop {slowness}")
    for i in range(int(slowness * 1e8)):
        i
    print(f"Wait for loop {slowness} finished")


async def main() -> None:
    await asyncio.gather(
        slow(1),
        slow(0.5),
        slow(0.1)
    )


if __name__ == '__main__':
    asyncio.run(main())

我希望 slowness=0.1 的函数首先完成执行,但我看到一个看似同步的常规执行。我做错了什么?

我看到以下输出:

Waiting for 1 seconds...
Wait for 1 seconds finished
Waiting for 0.5 seconds...
Wait for 0.5 seconds finished
Waiting for 0.1 seconds...
Wait for 0.1 seconds finished

我希望是这样的:

Waiting for 1 seconds...
Waiting for 0.5 seconds...
Waiting for 0.1 seconds...
Wait for 0.1 seconds finished
Wait for 0.5 seconds finished
Wait for 1 seconds finished

其他tasks/coroutines只有在当前正在执行的task/coroutine通过等待将控制权交还给事件循环时才会执行。 slow 不会等待任何事情,因此永远不会将控制权交还给事件循环,因此其他任务在当前任务完成之前不会执行。

await asyncio.sleep(0) 将放弃控制权,但会尽快执行

async def slow(slowness):
    print(f"Slow loop {slowness}")
    for i in range(int(slowness * 1e8)):
        await asyncio.sleep(0)
    print(f"Wait for loop {slowness} finished")

最好只睡适当的时间

async def slow(slowness):
    print(f"Slow loop {slowness}")
    await asyncio.sleep(slowness)
    print(f"Wait for loop {slowness} finished")

Asyncio 并不神奇。它不会突然赋予您的处理器三倍于当前的计算能力。我提供了这个简单的清单来确定 asyncio 是否可以加速你的程序:

  1. 我的程序是否花费大量时间等待资源,例如网络、数据库或(在我的情况下)一组仪器?
  2. 在等待期间,它是否可以做一些有用的事情?

如果这两个问题的答案都是肯定的,那么考虑使用 asyncio 来提高性能。否则不行。

这不是 asyncio 的唯一用例,但它是您似乎感兴趣的一个。Python 人们将 asyncio 文档放在“网络和进程间通信”下是有原因的比“并发执行”。

要加速数字运算类型的程序,您可能需要查看标准库中的多处理包,它支持真正的并行计算。