Discord bot在Cog中发送Embed报'int'对象无send属性错误
问题描述
我在把Discord机器人的命令拆分到Cog模块时遇到问题:目前Cog可以正常加载,但执行对应命令、机器人尝试向日志频道发送Embed消息时会运行失败。
相关实现代码如下:
from discord.ext import commands import datetime from ruamel.yaml import YAML yaml = YAML() with open(r"C:\Users\Jea\Desktop\Yuna-Discord-Bot\config.yml", "r", encoding="utf-8") as file: config = yaml.load(file) bot = commands.Bot(command_prefix=config['Prefix']) bot.debugchannel = config['Debug Channel ID'] bot.embed_color = discord.Color.from_rgb( config['Embed Settings']['Color']['r'], config['Embed Settings']['Color']['g'], config['Embed Settings']['Color']['b']) bot.footer = config['Embed Settings']['Footer']['Text'] bot.footerimg = config['Embed Settings']['Footer']['Icon URL'] class Testing(commands.Cog): def __init__(self, bot): self.bot = bot @bot.command(name="ping", aliases=["p"], help="Check if the bot is online with a simple command") async def ping(self, ctx): embed = discord.Embed(title=f"Pinged {bot.user}", color=bot.embed_color, timestamp=datetime.datetime.now(datetime.timezone.utc)) embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar_url) embed.set_footer(text=bot.footer, icon_url=bot.footerimg) await bot.debugchannel.send(embed=embed) print("Sent and embed") await ctx.message.add_reaction('✅') print("Added a reaction to a message") await ctx.send("Pong!") print("Sent a message") def setup(bot): bot.add_cog(Testing(bot)) print("Loaded testing cog")
运行时抛出的错误信息:
Traceback (most recent call last): File "C:\Users\Jea\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped ret = await coro(*args, **kwargs) File "c:\Users\Jea\Desktop\Yuna-Discord-Bot\cogs\testing.py", line 34, in ping await bot.debugchannel.send(embed=embed) AttributeError: 'int' object has no attribute 'send' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\Jea\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke await ctx.command.invoke(ctx) File "C:\Users\Jea\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke await injected(*ctx.args, **ctx.kwargs) File "C:\Users\Jea\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'int' object has no attribute 'send'
我已经确认问题出在await bot.debugchannel.send(embed=embed)这行,删掉这行之后命令就能正常运行,但不知道错误触发原因,需要对应的解决方案。
错误原因
报错AttributeError: 'int' object has no attribute 'send'的核心逻辑很明确:
你从配置文件读取到的Debug Channel ID是整数类型的频道ID,不是discord.py封装的频道对象,整数本身不存在send()方法,调用自然会报错。
除此之外你的代码还有3个Cog写法的常见问题:
- 缺失
discord模块导入,代码中用到的discord.Color、discord.Embed都会触发导入错误 - Cog内部注册命令应该用
@commands.command()装饰器,@bot.command()是主文件直接注册命令的写法,放在Cog里会出现注册时序异常 - Cog内部调用bot实例应该用
self.bot,不要直接引用全局bot变量,避免多实例加载时出现引用错误
修复方案
- 补上缺失的
discord模块导入 - 配置项只存储整数类型的频道ID即可,不要尝试在机器人启动前直接获取频道对象——此时机器人还未连接Discord服务器,根本拿不到频道实例
- 修正Cog内的命令装饰器,所有bot实例调用统一换成
self.bot - 实际发送消息时,先通过频道ID从机器人缓存中获取对应的频道对象,再调用
send()方法,可额外加判断避免频道不存在、机器人无权限访问时报错
修复后的完整参考代码:
# 补上缺失的discord导入 import discord from discord.ext import commands import datetime from ruamel.yaml import YAML yaml = YAML() with open(r"C:\Users\Jea\Desktop\Yuna-Discord-Bot\config.yml", "r", encoding="utf-8") as file: config = yaml.load(file) bot = commands.Bot(command_prefix=config['Prefix']) # 仅存储频道ID,不提前获取对象 bot.debug_channel_id = config['Debug Channel ID'] bot.embed_color = discord.Color.from_rgb( config['Embed Settings']['Color']['r'], config['Embed Settings']['Color']['g'], config['Embed Settings']['Color']['b']) bot.footer = config['Embed Settings']['Footer']['Text'] bot.footerimg = config['Embed Settings']['Footer']['Icon URL'] class Testing(commands.Cog): def __init__(self, bot): self.bot = bot # Cog内使用commands.command装饰器注册命令 @commands.command(name="ping", aliases=["p"], help="Check if the bot is online with a simple command") async def ping(self, ctx): # 命令触发时机器人已就绪,通过ID获取频道对象 debug_channel = self.bot.get_channel(self.bot.debug_channel_id) if debug_channel: embed = discord.Embed(title=f"Pinged {self.bot.user}", color=self.bot.embed_color, timestamp=datetime.datetime.now(datetime.timezone.utc)) embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar_url) embed.set_footer(text=self.bot.footer, icon_url=self.bot.footerimg) await debug_channel.send(embed=embed) print("Sent an embed") await ctx.message.add_reaction('✅') print("Added a reaction to a message") await ctx.send("Pong!") print("Sent a message") def setup(bot): bot.add_cog(Testing(bot)) print("Loaded testing cog")
注意:
get_channel依赖机器人本地缓存,仅能在on_ready事件触发后正常返回结果,命令触发时机器人已经完成缓存加载,所以这种写法没问题。如果需要在初始化阶段获取频道,要改用异步方法await self.bot.fetch_channel(频道ID)从接口拉取数据。
内容的提问来源于stack exchange,提问作者Jea
相关产品推荐
相关产品推荐

