单脚本无警告运行多个discord.py机器人方案咨询
实现目标
使用相同命令同时运行多个Discord机器人。
错误原因说明
单个discord.py的Bot/Client实例仅能维护一个与Discord网关的WebSocket连接,无法同时绑定多个账号Token。对同一个客户端实例重复调用start()方法传入多个Token,会导致两个协程同时抢占同一个WebSocket连接的消息接收通道,触发RuntimeError: Concurrent call to receive() is not allowed报错,同时会因为连接未正常释放出现未关闭连接器的资源警告。
无冗余最优实现
不需要重复复制粘贴多份客户端配置代码,通过工厂函数统一封装公共配置即可,需要新增机器人时仅需添加对应Token,无需重复编写逻辑:
import asyncio from os import getenv, listdir import discord from discord.ext import commands from discord_slash import SlashCommand # 公共配置工厂,所有复用逻辑仅需编写一次 def build_bot(): intents = discord.Intents().all() bot = commands.Bot(command_prefix='.', intents=intents) SlashCommand(bot, sync_commands=True) bot.remove_command('help') # 公共事件注册 @bot.event async def on_ready(): await bot.change_presence(activity=discord.Game(name='Bot Ready')) print(f"登录成功:{bot.user}") # 统一加载Cog模块 for filename in listdir('cogs'): if filename.endswith('.py'): bot.load_extension(f'cogs.{filename[:-3]}') # 公共权限校验逻辑 def owner_check(ctx): return ctx.author.id == 385053392059236353 bot.add_check(owner_check) return bot async def run_all_bots(): # 填入所有需要启动的机器人Token token_list = [getenv("TOKEN1"), getenv("TOKEN2")] # 批量生成独立的机器人实例 bot_instances = [build_bot() for _ in token_list] # 并发启动所有实例 await asyncio.gather(*[bot.start(token) for bot, token in zip(bot_instances, token_list)]) if __name__ == "__main__": asyncio.run(run_all_bots())
方案特性
- 无代码冗余:所有公共配置、事件、Cog加载、校验逻辑仅在工厂函数中编写一次,新增机器人无需重复复制代码
- 运行无报错警告:每个机器人持有独立的客户端实例、WebSocket连接与aiohttp会话,不存在连接抢占问题,资源可正常回收
- 易扩展:后续新增机器人仅需在
token_list中添加对应Token即可,无需修改其他逻辑 - 注意事项:如果Cog模块中存在全局状态变量,需要修改为绑定到Bot实例的属性,避免多机器人之间状态串扰
内容的提问来源于stack exchange,提问作者user17648826
相关产品推荐
相关产品推荐

