如果父函数不是异步的,我如何在异步任务中并行睡眠()?

Posted

技术标签:

【中文标题】如果父函数不是异步的,我如何在异步任务中并行睡眠()?【英文标题】:How can I sleep() parallely inside asyncio task if parent function isn't async? 【发布时间】:2021-10-11 06:27:07 【问题描述】:

代码:

class App:
    def __init__(self):
        # some of the code
        ...
        ...
        xxx.add_handler(self.event_handler, event_xyz)
        asyncio.create_task(self.keep_alive())
        xxx.run_until_disconnected()

    def keep_alive(self):
        # stuff to keep connection alive
        ...
        ...
        time.sleep(5) # this will block whole script
        asyncio.sleep(5) # this won't work because of lack of async on _init_ and keep_alive
    
    async def event_handler(self):
        await stuff
    
    # other functions

if __name__ == '__main__':
    App()

保持连接活动的代码部分有 api 限制。所以,我需要在keep_alive() 函数中加入sleep 语句。

我知道可以完全更改代码的设计以使其正常工作,但它是一个大脚本,其他一切都运行良好。所以,最好是如果这可以工作。 只要其余代码在sleep 期间没有被阻塞,我就可以使用其他任何东西,例如线程。

【问题讨论】:

您的代码中是否有 ansycio 事件循环,或者这是您需要的唯一异步内容? @Blckknght 用 event_handler 部分更新了代码,它是异步函数。 【参考方案1】:

这是一个简单的情况。 time.sleep 阻塞当前线程,包括该线程的异步事件循环(如果有的话)。时期。结案。

如果您的 API 要求您进行 time.sleep 调用,并且您的程序必须在当前线程处于休眠状态时执行某些操作,那么 asyncio 不是解决方案。这并不意味着 asyncio 在你的程序设计中不能用于其他线程或其他目的,但它绝对不能在 time.sleep 间隔期间在当前线程中运行其他任务。

关于代码 sn-p 中的函数 keep_alive:此函数不能成为任务,因为它没有声明为“async def”。从这种类型的常规函数​​内部调用 asyncio.sleep() 是错误的;它必须始终是“等待的”,并且“等待”关键字必须在 async def 函数中。另一方面,在 async def 函数中调用 time.sleep 是 not 错误,并且该函数将按预期工作。但这可能不是你想做的事情。

【讨论】:

以上是关于如果父函数不是异步的,我如何在异步任务中并行睡眠()?的主要内容,如果未能解决你的问题,请参考以下文章

如何异步运行函数以使用 Django 应用在 Heroku 上并行计算?

iOS面试系列-2多线程中同步异步和串行并行之间的逻辑关系(必考,必须掌握)

异步并行任务实现的几种方案

我如何在异步中使用请求?

异步等待和并行

如何使用 C#8 IAsyncEnumerable<T> 来异步枚举并行运行的任务