如何调用async异步函数并阻塞所有其他协程直至其执行完成?
解决方案
注意:不要尝试用同步阻塞的方式卡住事件循环,否则Motor的异步IO操作会完全停止,初始化流程也无法完成,我们只需要阻塞业务逻辑的执行即可
你不需要同时引入PyMongo和Motor,用以下两种方案即可实现需求:
方案1:重写事件派发方法(最省心,无需修改现有业务逻辑)
discord.py的所有事件都会经过dispatch方法派发,你可以重写这个方法,在数据库初始化完成前拦截所有非必要事件:
- 给你的Bot/Client类新增就绪状态标记:
# 在类的__init__方法中添加 self.db_ready = False
- 重写dispatch方法:
async def dispatch(self, event_name: str, *args, **kwargs): # 仅放行connect事件,其他事件在数据库就绪前全部拦截 if not self.db_ready and event_name != "connect": return await super().dispatch(event_name, *args, **kwargs)
- 在
init_database的最后一行修改标记位:
async def init_database(self): # 你的原有数据库校验逻辑,所有异步操作都正常用await/asyncio.gather等待即可 self.db_ready = True
方案2:初始化完成后再启动机器人(适合不需要Discord连接数据的场景)
如果你的init_database逻辑不需要调用Discord相关接口,完全可以在启动机器人前先跑完初始化流程,从根源上避免初始化期间有事件触发:
import asyncio async def main(): bot = YourBotClass() # 先跑完数据库初始化 await bot.init_database() # 再启动机器人连接Discord await bot.start("你的机器人token") asyncio.run(main())
关于子协程执行的说明
只要你在init_database内部把所有子异步任务都显式等待(比如并行任务用await asyncio.gather(任务1, 任务2...),串行任务直接依次await),await init_database()就会等所有内部子协程全部执行完成才会返回,不会出现提前结束的问题。
内容的提问来源于stack exchange,提问作者Kirk KD
相关产品推荐
相关产品推荐

