Python3.10+Discord.py2.0:扩展模块装饰器复用主模块配置值
解决方案
针对你遇到的「将config中的Guild ID传入Cog装饰器且不重复读取配置」的问题,有两种实用方案:
方案一:在setup函数中动态配置命令的Guild范围
装饰器在类定义阶段就会执行,此时__init__还未初始化,无法直接通过bot.config获取值。但setup函数在加载Cog时执行,此时已能访问bot实例,可通过动态修改命令属性实现需求:
修改cogs/extension.py:
from discord import app_commands from discord.ext import commands class MyCog(commands.Cog): def __init__(self, bot): self.bot = bot @app_commands.command(name='mycommand') # 移除原有的@app_commands.guilds()装饰器 async def command(self, interaction): # 执行命令逻辑 await interaction.response.send_message("命令执行成功") async def setup(bot): cog = MyCog(bot) # 从bot实例获取配置中的Guild ID,转为discord.Object target_guild = app_commands.Object(id=int(bot.config['guild_id'])) # 给指定命令添加Guild范围 cog.command.guilds.append(target_guild) # 若Cog中有多个命令,可批量处理: # for cmd in cog.walk_app_commands(): # cmd.guilds.append(target_guild) await bot.add_cog(cog)
方案二:将配置抽为独立模块(更优雅)
把配置读取逻辑单独放在一个模块中,整个项目仅读取一次配置,所有模块直接导入使用,避免装饰器阶段无法访问bot实例的问题:
- 创建
config.py文件:
import json # 仅读取一次配置 with open('config.json', 'r') as f: config = json.load(f)
- 修改
main.py:
from config import config import discord from discord.ext import commands import os import asyncio bot = commands.Bot(prefix='!', intents=discord.Intents.all()) bot.config = config # 保留这行以便Cog中仍能通过bot访问(可选) async def load_cogs(): for filename in os.listdir('cogs/'): if filename.endswith('.py'): await bot.load_extension(f'cogs.{filename[:-3]}') async def main(): await load_cogs() await bot.start(bot.config['TOKEN']) # 这里也可以直接用config['TOKEN'] asyncio.run(main())
- 修改
cogs/extension.py:
from config import config from discord import app_commands from discord.ext import commands class MyCog(commands.Cog): def __init__(self, bot): self.bot = bot @app_commands.command(name='mycommand') # 直接从config模块获取Guild ID @app_commands.guilds(app_commands.Object(id=int(config['guild_id']))) async def command(self, interaction): # 执行命令逻辑 await interaction.response.send_message("命令执行成功") async def setup(bot): await bot.add_cog(MyCog(bot))
注意事项
- 确保
config.json中的guild_id是字符串或可转为整数的类型,discord.Object需要传入整数ID。 - 方案一无需调整项目结构,适合小型项目;方案二配置集中管理,更利于大型项目维护。
内容的提问来源于stack exchange,提问作者xord
相关产品推荐
相关产品推荐

