discord.py通过ID获取User对象失败?解决spam命令报错问题
解决Discord机器人发送DM Ping时的AttributeError问题
看来你的机器人突然罢工是因为client.get_user()返回了None,导致你访问user.name时触发了属性错误。我来给你拆解问题原因和修复方案:
为什么会出现这个问题?
- 缓存丢失:Heroku的免费实例会定期休眠重启,重启后机器人的本地用户缓存会被清空,
get_user()只能从缓存里取数据,自然找不到用户返回None。 - 用户不在同一服务器:如果你的机器人和目标用户没有共享任何服务器,
get_user()也会返回None——Discord机器人默认只能获取自己所在服务器内的用户缓存。
具体修复步骤
1. 替换get_user为fetch_user
fetch_user()会直接调用Discord API获取用户信息,不依赖本地缓存,在Heroku这种经常重启的环境里更可靠。而且它还能帮你捕获“用户不存在”的情况。
2. 增加异常处理
不管是找不到用户,还是发送DM失败(比如用户关了陌生人消息),都要加异常处理,避免整个命令崩溃。
3. 先验证用户存在再操作
在使用user对象的任何属性前,先确认它不是None,或者直接用try-except捕获API调用的异常。
修改后的可运行代码
from discord.ext import commands import discord token = 'MyBotTokenHere' prefix = '.' client = commands.Bot(command_prefix=prefix) client.remove_command("help") @client.event async def on_ready(): print('Ready') @client.command() async def spam(ctx, id1: int, num: int): # 先尝试通过API获取用户,处理找不到的情况 try: user = await client.fetch_user(id1) except discord.NotFound: await ctx.send("❌ 找不到该用户,请检查用户ID是否正确,且机器人和用户在同一服务器!") return await ctx.send(f'✅ 开始给{user.name}发送{num}次Ping消息!') successful_pings = 0 for _ in range(num): try: await user.send(f'<@{id1}>') successful_pings += 1 except discord.Forbidden: await ctx.send(f'⚠️ 无法给{user.name}发送DM,可能用户关闭了陌生人消息或屏蔽了机器人!') break except Exception as e: await ctx.send(f'❌ 发送消息时出错:{str(e)}') break await ctx.send(f'🏁 Ping任务完成!成功发送{successful_pings}条消息(共请求{num}次)') client.run(token)
额外提醒
- 必须保证机器人和目标用户在至少一个共同服务器里,否则即使能获取用户信息,也发不了DM——这是Discord的安全限制。
- 不要一次性发送太多Ping,避免触发Discord的API速率限制,轻则机器人被限流,重则被封禁。
- Heroku重启后缓存清空是常态,以后尽量用
fetch_user代替get_user来获取用户信息。
内容的提问来源于stack exchange,提问作者PythonSnek
相关产品推荐
相关产品推荐

