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

如何将discord.py的事件处理代码拆分到独立文件中

Discord.py 日志功能模块化实现方案

discord.py 原生提供了 Cog 机制专门做功能拆分,不需要自己手写复杂的导入绑定逻辑,是目前最稳妥的模块化方案,拆分后主文件只需要保留启动逻辑,所有日志相关的事件处理都可以独立到单独文件里。

第一步:调整目录结构

先把文件按功能拆分,推荐结构如下:

your_bot/
├── main.py          # 机器人启动入口
├── cogs/            # 所有模块化功能存放目录
│   ├── __init__.py  # 空文件即可,标记为Python包
│   └── log_event.py # 所有日志相关事件处理放这里
└── utils/
    └── log_util.py  # 你原来写的Logging工具类移到这里

第二步:编写日志模块Cog

把你原来写的所有事件监听代码移到cogs/log_event.py里,替换成Cog写法:

from discord.ext import commands
import discord
from utils.log_util import Logging

class LogCog(commands.Cog):
    def __init__(self, bot: commands.Bot):
        self.bot = bot
        # 全局复用一个Logging实例,不要每次触发事件都新建
        self.logger = Logging()

    # 用Cog自带的监听器装饰器代替原来的@bot.event
    @commands.Cog.listener()
    async def on_message_delete(self, m):
        # 过滤机器人自身消息,避免无效日志
        if m.author.bot:
            return
        created_at = m.created_at.strftime('%d-%m-%Y %H:%M:%S')
        log_content = f'{m.author} deleted message.\n[{created_at}] "{m.content}"'
        await self.logger.write_log(1, log_content)

    @commands.Cog.listener()
    async def on_message_edit(self, m_before, m_after):
        if m_after.author.bot:
            return
        # 过滤内容没变化的编辑事件(比如嵌入卡片加载触发的自动edit)
        if m_before.content == m_after.content:
            return
        created_at = m_after.created_at.strftime('%d-%m-%Y %H:%M:%S')
        edited_at = m_after.edited_at.strftime('%d-%m-%Y %H:%M:%S')
        log_content = f'{m_after.author} edited message.\n[{created_at}] "{m_before.content}"\n[{edited_at}] "{m_after.content}"'
        await self.logger.write_log(1, log_content)

    @commands.Cog.listener()
    async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
        if payload.member.bot:
            return
        channel = self.bot.get_channel(payload.channel_id)
        message = await channel.fetch_message(payload.message_id)
        created_at = message.created_at.strftime('%d-%m-%Y %H:%M:%S')
        # 修正原代码里addded的拼写错误
        log_content = f'{payload.member} added reaction {payload.emoji} to message from {message.author}.\n[{created_at}] "{message.content}"'
        await self.logger.write_log(2, log_content)

    @commands.Cog.listener()
    async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent):
        channel = self.bot.get_channel(payload.channel_id)
        message = await channel.fetch_message(payload.message_id)
        # 原代码这里有bug:raw移除反应事件的payload不带member属性,要自己通过user_id查
        user = self.bot.get_user(payload.user_id)
        created_at = message.created_at.strftime('%d-%m-%Y %H:%M:%S')
        log_content = f'{user} removed reaction {payload.emoji} from message by {message.author}.\n[{created_at}] "{message.content}"'
        await self.logger.write_log(2, log_content)

# Cog固定加载入口,主文件直接调用即可
async def setup(bot: commands.Bot):
    await bot.add_cog(LogCog(bot))

第三步:修改主启动文件

原来主文件里堆的所有日志相关事件代码全删掉,只保留启动和加载Cog的逻辑即可:

import discord
from discord.ext import commands
import os
from dotenv import load_dotenv

load_dotenv()
# 记得开启对应权限的intents,否则事件无法触发
intents = discord.Intents.default()
intents.message_content = True
intents.reactions = True

bot = commands.Bot(command_prefix='!', intents=intents)

# 启动钩子中加载日志模块
@bot.event
async def setup_hook():
    await bot.load_extension('cogs.log_event')
    print("日志模块加载完成")

bot.run(os.getenv('BOT_TOKEN'))

补充说明

  • 后续要加新的日志事件,直接在LogCog类里新增对应监听函数即可,不需要修改主文件
  • 其他功能(比如审核、娱乐命令、定时任务)都可以按同样的逻辑拆成独立Cog文件,互相完全不耦合
  • 如果你不想用Cog,也可以手动在单独的events文件里写接收bot参数的注册函数,内部用@bot.event绑定事件,但这种方式后续扩展命令、做权限控制都很麻烦,不推荐
  • 注意要在Discord开发者后台对应机器人的页面开启Message Content Intent等开关,否则部分事件不会推送

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:36:15