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 是否可以加速你的程序:
- 我的程序是否花费大量时间等待资源,例如网络、数据库或(在我的情况下)一组仪器?
- 在等待期间,它是否可以做一些有用的事情?
如果这两个问题的答案都是肯定的,那么考虑使用 asyncio 来提高性能。否则不行。
这不是 asyncio 的唯一用例,但它是您似乎感兴趣的一个。Python 人们将 asyncio 文档放在“网络和进程间通信”下是有原因的比“并发执行”。
要加速数字运算类型的程序,您可能需要查看标准库中的多处理包,它支持真正的并行计算。
我在 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 是否可以加速你的程序:
- 我的程序是否花费大量时间等待资源,例如网络、数据库或(在我的情况下)一组仪器?
- 在等待期间,它是否可以做一些有用的事情?
如果这两个问题的答案都是肯定的,那么考虑使用 asyncio 来提高性能。否则不行。
这不是 asyncio 的唯一用例,但它是您似乎感兴趣的一个。Python 人们将 asyncio 文档放在“网络和进程间通信”下是有原因的比“并发执行”。
要加速数字运算类型的程序,您可能需要查看标准库中的多处理包,它支持真正的并行计算。