如何实现可同时收发消息的Discord Bot?
Discord Bot 实现控制台收发消息的问题解决
我正在开发一个Discord Bot,希望实现同时在控制台读取他人消息并发送消息的功能。
最初的尝试与问题
最初尝试了以下代码,但存在阻塞问题——必须先输入要发送的内容,才能显示他人发送的消息:
@client.event async def on_message(message): channel = message.channel content = message.content user = message.author talk = input('>') await channel.send(talk) print(f'{user} - {content}')
多线程尝试的错误
查阅资料后尝试用多线程解决,但方案仍然无法正常运行:
@client.event async def on_message(message): channel = message.channel talk = input('>') await channel.send(talk) def read(message): content = message.content user = message.author print(f'{user} - {content}') threadObj = threading.Thread(target=read(message)) threadObj.start()
问题根源
input()是阻塞式函数,放在on_message事件里会卡住Discord的事件循环,导致必须完成输入才会处理消息打印- 多线程用法错误:
target=read(message)是直接执行了read函数,而非将函数作为线程目标;且逻辑搞反,应该把控制台输入放到线程里,而非消息处理
正确解决方案
将控制台输入逻辑单独放到线程中,避免阻塞事件循环;on_message仅负责处理收到的消息:
完整代码示例
import discord import threading import asyncio from discord.ext import commands # 初始化Bot,需要开启消息内容权限 intents = discord.Intents.default() intents.message_content = True client = commands.Bot(command_prefix="!", intents=intents) def console_input_loop(): """控制台输入线程:持续读取输入并发送到指定频道""" while True: talk = input('>') # 替换为你要发送的频道ID target_channel = client.get_channel(1234567890) if target_channel: # 在非异步线程中调用异步发送方法 asyncio.run_coroutine_threadsafe(target_channel.send(talk), client.loop) @client.event async def on_ready(): print(f'已登录为 {client.user}') # 启动控制台输入线程,daemon=True让线程随主程序退出 threading.Thread(target=console_input_loop, daemon=True).start() @client.event async def on_message(message): # 忽略Bot自身发送的消息 if message.author == client.user: return # 打印收到的消息 print(f'{message.author} - {message.content}') # 若需要处理命令,保留此行 await client.process_commands(message) # 替换为你的Bot令牌 client.run('your_bot_token_here')
关键说明
- 控制台输入线程:将
input()放到单独线程中,避免阻塞Discord的事件循环 - 异步调用兼容:用
asyncio.run_coroutine_threadsafe在非异步线程中调用Discord的异步方法,确保和事件循环兼容 - 消息处理分离:
on_message仅负责打印收到的消息,不再处理输入逻辑,不会被阻塞
内容的提问来源于stack exchange,提问作者user19742894
相关产品推荐
相关产品推荐

