【问题标题】:Slow function in python not running asyncronouslypython中的慢速函数没有异步运行
【发布时间】:2021-12-29 10:27:04
【问题描述】:

我在 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

【问题讨论】:

    标签: python asynchronous python-asyncio


    【解决方案1】:

    只有当当前正在执行的任务/协程通过等待将控制权交还给事件循环时,才会执行其他任务/协程。 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")
    

    【讨论】:

      【解决方案2】:

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

      1. 我的程序是否花费大量时间等待资源,例如网络、数据库或(在我的情况下)一组仪器?
      2. 在它等待的时候,有什么有用的东西可以代替它吗?

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-15
        • 2022-07-06
        • 2018-09-24
        • 1970-01-01
        • 2022-11-16
        • 2021-03-19
        • 2020-12-14
        • 1970-01-01
        相关资源
        最近更新 更多