如何在等待用户输入时让Discord bot正常接收并打印消息
解决方案
核心问题原因
- 原代码中
input()是同步阻塞函数,直接放在异步的on_message回调中会卡死discord.py的异步事件循环,导致新消息接收、后台同步等所有逻辑全部停转 on_message是消息触发回调,每收到一条新消息会自动执行一次,不需要额外加无限while循环,多余的死循环会进一步阻塞逻辑- 多线程不生效是因为没有把阻塞的输入逻辑和异步事件循环拆开,跨线程调用异步函数需要通过
asyncio.run_coroutine_threadsafe提交任务,不能直接调用await
修复后可运行代码
import discord import asyncio import threading # 全局变量存储异步事件循环和当前活跃发送频道 loop = None current_channel = None # 需开启消息内容意图才能正常接收消息 intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) @client.event async def on_ready(): global loop loop = asyncio.get_running_loop() print('Logged in as {0.user}'.format(client)) @client.event async def on_message(message): global current_channel # 忽略自身发送的消息 if message.author == client.user: return # 更新当前活跃频道为最新收到消息的频道 current_channel = message.channel # 新消息收到直接打印,无需等待输入 username = str(message.author).split('#')[0] print(f'\n{username} : {message.content}') # 保留输入提示,优化输入体验 print('You: ', end='', flush=True) # 单独线程运行用户输入逻辑,不阻塞主事件循环 def input_handler(): while True: answer = input('You: ') if not current_channel or not loop: print('暂无可发送的频道,请等待收到消息后重试') continue # 跨线程提交发送任务到异步事件循环 asyncio.run_coroutine_threadsafe(current_channel.send(answer), loop) if __name__ == '__main__': # 启动输入守护线程,主程序退出时自动销毁 threading.Thread(target=input_handler, daemon=True).start() # 替换为你自己的Bot Token client.run('你的Bot TOKEN')
功能说明
- 所有新消息收到后会直接打印到控制台,哪怕你正在输入内容也不会漏消息,解决多消息堆叠的问题
- 输入内容默认发送到最新发来消息的频道,你可以根据需求扩展多频道切换逻辑
- 使用前需要先在Discord开发者后台的Bot设置页开启
Message Content Intent权限,否则无法正常读取消息内容
内容的提问来源于stack exchange,提问作者KAOTU
相关产品推荐
相关产品推荐

