You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py on_member_remove事件报NoneType对象无send属性错误

报错原因

控制台抛出AttributeError: 'NoneType' object has no attribute 'send'的直接原因是bot.get_channel(id=myLogChannelIdHere)返回了None,即机器人没有从本地缓存中找到对应ID的频道。你写在on_ready里的同逻辑代码可以正常运行,是因为on_ready的触发节点恰好是机器人首次完成全局缓存加载的时刻,此时频道数据已经存入缓存;而成员加入/离开事件触发时,大概率遇到了以下问题:

  • 未开启Discord要求的特权网关意图(核心是Server Members Intent),导致机器人无法完整同步服务器的频道、成员数据,缓存缺失
  • bot.get_channel()仅读取本地缓存,在机器人刚启动、断线重连等缓存未加载/刷新完成的场景下,即使频道ID完全正确,也会返回None
  • 你当前编写的Embed代码存在语法错误,即使频道获取正常,后续也会触发其他运行时异常

修复方案

1. 配置特权网关意图

首先前往Discord开发者门户,进入你的机器人应用的「Bot」设置页,下拉到Privileged Gateway Intents板块,开启以下三个开关后保存:

  • Server Members Intent(接收成员加入/离开事件的强制要求)
  • Message Content Intent
  • Presence Intent

随后修改机器人初始化代码,显式声明启用的intents:

import discord
from discord.ext import commands
import datetime

# 替换为你自己的配置,注意频道ID必须是整数类型,不要加引号
BOT_PREFIX = "!"
MY_LOG_CHANNEL_ID = 123456789012345678

intents = discord.Intents.default()
intents.members = True
intents.guilds = True
intents.messages = True
bot = commands.Bot(command_prefix=BOT_PREFIX, intents=intents)

2. 优化频道获取逻辑,增加兜底判断

不要在每个事件中重复调用get_channel,建议在on_ready触发时将日志频道实例存为全局变量,同时增加API兜底逻辑,避免缓存失效导致程序崩溃:

# 全局变量存储日志频道实例
log_channel = None

@bot.event
async def on_ready():
    global log_channel
    # 每次触发on_ready(包括断线重连)都重新获取频道实例,保证缓存有效
    log_channel = bot.get_channel(MY_LOG_CHANNEL_ID)
    # 缓存读取失败时,主动调用API获取频道做兜底
    if not log_channel:
        try:
            log_channel = await bot.fetch_channel(MY_LOG_CHANNEL_ID)
        except Exception as e:
            print(f"日志频道获取失败: {str(e)}")
            return
    await bot.change_presence(
        status=discord.Status.online,
        activity=discord.Activity(type=discord.ActivityType.watching, name="")
    )
    await log_channel.send("Le bot est en ligne")
    print(f"{bot.user.name} est en ligne")

3. 修正成员离开事件的代码错误

你原有代码存在三处语法问题:一是set_thumbnail是Embed的实例方法,不是构造函数的传入参数;二是f字符串中多写了多余的$符号;三是discord.py 2.0+版本中,成员头像地址需要通过member.avatar.url获取,旧属性avatar_url已经废弃。修正后的代码如下:

@bot.event
async def on_member_remove(member):
    global log_channel
    # 频道实例不存在时直接终止逻辑,避免抛出空值错误
    if not log_channel:
        return
    embed = discord.Embed(
        title="**🚪 Un membre est parti**",
        description=f"{member} a quitté le serveur",
        color=0xda291c
    )
    # 正确设置头像缩略图,成员无自定义头像时跳过避免报错
    if member.avatar:
        embed.set_thumbnail(url=member.avatar.url)
    embed.timestamp = datetime.datetime.utcnow()
    await log_channel.send(embed=embed)

注意事项
  • 提前确认机器人在日志频道拥有发送消息、嵌入链接的权限,权限不足同样会导致消息发送失败
  • on_ready事件会在机器人每次断线重连时触发,将频道获取逻辑放在此处可以自动更新缓存的频道实例,避免机器人长期运行后缓存失效
  • 所有ID类配置(频道ID、服务器ID、用户ID)都必须传入整数类型,传入字符串会导致get_channel无法匹配到对应资源

内容的提问来源于stack exchange,提问作者Max.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:12:23