discord.py如何正确获取Guild实例 解决get_guild返回None报错
报错根因
你遇到的NoneType报错核心是执行时序错误:
- 脚本里在Bot刚完成实例化的阶段,就直接调用
bot.get_guild()获取服务器对象,但此时Bot还没有和Discord的网关建立连接,本地的服务器、角色缓存全是空的。刚创建的commands.Bot实例不会自带任何Discord端的业务数据,必须等Bot走完完整连接流程、触发on_ready就绪事件后,才会把它加入的所有服务器的信息、角色、频道数据同步到本地缓存,这时候调用get_guild才能拿到有效的Guild实例。
因为discord.py是异步框架,脚本顶层的同步代码会在Bot启动流程前就执行完毕,根本等不到连接Discord、同步缓存的步骤,所以把获取实例的逻辑写在顶层永远拿不到有效数据。
- 代码里还有两处容易踩的坑:
- 给
DEAFENED常量匹配角色时,传入的名称参数是'Undeafened',和变量本身的语义、实际要找的角色不匹配,很容易取到None - 没有对
get_guild、角色查找的返回值做有效性校验,一旦填错服务器ID、角色名拼写不对,就会直接触发访问None对象属性的报错
- 给
正确的实现方式
把Guild、角色的获取逻辑放到on_ready事件回调里,通过global关键字把提前定义的全局常量和获取到的实例关联起来,保证Bot整个运行周期内都可以随时调用这些常量:
import discord from discord.ext import commands # 顶层提前声明常量,明确作用域,方便全局引用 MAIN_GUILD: discord.Guild UNMUTED: discord.Role DEAFENED: discord.Role # 配置Bot的必要权限意图,保证能拉取到完整的服务器、角色数据 intents = discord.Intents.default() intents.guilds = True intents.members = True bot = commands.Bot(command_prefix='~', intents=intents) @bot.event async def on_ready(): global MAIN_GUILD, UNMUTED, DEAFENED MAIN_GUILD_ID = 123456789012345678 # 替换为实际目标服务器的ID # 获取服务器实例,加存在性判断 MAIN_GUILD = bot.get_guild(MAIN_GUILD_ID) if not MAIN_GUILD: print(f"未找到ID为{MAIN_GUILD_ID}的服务器,请确认机器人已加入该服务器、ID填写正确") return # 从服务器的角色列表中匹配目标角色 UNMUTED = discord.utils.get(MAIN_GUILD.roles, name="Unmuted") DEAFENED = discord.utils.get(MAIN_GUILD.roles, name="Deafened") # 校验角色存在性,避免后续调用时触发None属性报错 if not UNMUTED: print("未检索到名为Unmuted的角色,请检查角色名拼写") if not DEAFENED: print("未检索到名为Deafened的角色,请检查角色名拼写") print("机器人启动完成,所有全局角色常量已初始化") bot.run("你的机器人登录Token")
注意事项
- 必须在Discord开发者后台为机器人开启Guilds、Server Members对应的意图权限,否则即使代码逻辑正确,也可能因为权限拉不到完整的缓存数据,导致
get_guild返回None - 所有需要依赖Discord业务数据的操作,都不要在脚本的顶层位置直接执行,统一放到事件回调、命令回调中触发,这些场景下Bot已经完成连接初始化,本地缓存是可用的
- 如果担心on_ready触发前的空窗期导致常量未定义,可以先在顶层给常量设置一个初始占位值,等on_ready回调执行时再覆盖成实际的实例。
内容的提问来源于stack exchange,提问作者Simos Neopoulos
相关产品推荐
相关产品推荐

