Discord Bot重复调用时日志双倍/三倍重复的问题排查与解决
Discord Bot重复调用后日志重复输出问题解决
问题说明
开发了一个简单的Discord Bot,仅用于初始化时向指定频道发送字符串列表作为项目通知模块。功能正常,但重复调用run_discord_bot函数时,控制台日志会出现双倍、三倍的重复输出。尝试用log_handler=None关闭日志会完全移除所有日志,需要解决日志重复的问题。
现有代码
import discord from discord.ext import commands def run_discord_bot(list_to_print): client = commands.Bot(command_prefix='!', intents=discord.Intents.all()) @client.event async def on_ready(): print("working!") channel = client.get_channel(MY CHANNEL ID) for item in list_to_print: await channel.send(item) await client.close() client.run("MY TOKEN") run_discord_bot(["msg1", "msg2"]) run_discord_bot(["msg3", "msg4"]) run_discord_bot(["msg5", "msg6"])
控制台日志示例
[2023-06-14 00:50:00] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:01] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id1). working! [2023-06-14 00:50:04] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:04] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:05] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id2). [2023-06-14 00:50:05] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id2). working! [2023-06-14 00:50:07] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:07] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:07] [INFO ] discord.client: logging in using static token [2023-06-14 00:50:08] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id3). [2023-06-14 00:50:08] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id3). [2023-06-14 00:50:08] [INFO ] discord.gateway: Shard ID None has connected to Gateway (Session ID: id3). working! Process finished with exit code 0
问题原因
discord.py的日志系统是全局共享的,每次调用run_discord_bot创建新的commands.Bot实例时,client.run()方法会自动为discord命名空间的日志器添加一个StreamHandler(控制台输出处理器)。多次调用后,日志器会累积多个相同的处理器,每条日志会被所有处理器分别输出一次,导致日志重复次数与函数调用次数一致。
解决方法
方法1:重构代码,复用单个Bot实例(推荐)
反复创建Bot实例并登录登出不仅会导致日志重复,还可能触发Discord API的频率限制。最优方案是只初始化一次Bot,复用它完成所有消息发送任务:
import discord from discord.ext import commands import asyncio # 替换为你的频道ID和Bot令牌 MY_CHANNEL_ID = 123456789012345678 MY_TOKEN = "your_bot_token_here" async def send_notifications(client, message_list): # 等待Bot完成初始化连接 await client.wait_until_ready() channel = client.get_channel(MY_CHANNEL_ID) if channel: for msg in message_list: await channel.send(msg) async def main(): # 仅初始化一次Bot实例 intents = discord.Intents.all() client = commands.Bot(command_prefix='!', intents=intents) async with client: # 批量发送消息 await send_notifications(client, ["msg1", "msg2"]) await send_notifications(client, ["msg3", "msg4"]) await send_notifications(client, ["msg5", "msg6"]) # 发送完成后关闭连接 await client.close() if __name__ == "__main__": asyncio.run(main())
方法2:清理重复的日志处理器(兼容原有调用逻辑)
如果必须保留多次调用run_discord_bot的逻辑,可以在每次创建Bot实例前,清理discord日志器中已存在的处理器:
import discord from discord.ext import commands import logging # 替换为你的频道ID和Bot令牌 MY_CHANNEL_ID = 123456789012345678 MY_TOKEN = "your_bot_token_here" def run_discord_bot(list_to_print): # 清理discord日志器的重复处理器 discord_logger = logging.getLogger('discord') while discord_logger.handlers: discord_logger.removeHandler(discord_logger.handlers[0]) client = commands.Bot(command_prefix='!', intents=discord.Intents.all()) @client.event async def on_ready(): print("working!") channel = client.get_channel(MY_CHANNEL_ID) for item in list_to_print: await channel.send(item) await client.close() client.run(MY_TOKEN) # 保留原有调用逻辑 run_discord_bot(["msg1", "msg2"]) run_discord_bot(["msg3", "msg4"]) run_discord_bot(["msg5", "msg6"])
内容的提问来源于stack exchange,提问作者Jakub222444
相关产品推荐
相关产品推荐

