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

Discord.py日志系统无法下载当日日志触发HTTPException求助

Discord.py 日志系统问题修复

核心报错根源

  • 遇到的「无法发送空消息」HTTPException,本质是Discord API的规则:不允许上传0字节的空文件,而当日生成的日志文件恰好因为代码逻辑bug成了无内容的空文件
  • 造成空文件的逻辑漏洞:create_log函数里,外层用"x"独占模式打开新建文件时,文件句柄全程被持有,紧接着在这个未关闭的上下文里调用append_new_line写入日志头——多数操作系统下,被独占模式打开的文件会被加锁,后续的写入操作根本无法落盘,最后留下的就是没有任何内容的空文件
  • 现有异常捕获完全失效:把「文件不存在、权限不足、Discord API拒绝空文件」所有异常都笼统归到discord.HTTPException直接pass,既不给用户反馈,也没法定位真实问题,甚至当文件真的不存在时,根本走不到HTTP异常分支,直接抛出未捕获的FileNotFoundError
  • 额外的边界问题:所有时间计算都用服务器本地时区,和日志里标注的CET时区不统一,跨时区部署时很容易出现文件名和实际日志日期错位的问题;当日无任何消息时,没有给日志文件加兜底内容,很容易出现空文件的情况。

修正后的实现

1. 修复文件锁导致的写入失败问题

调整create_log逻辑,新建文件后立刻释放句柄,再执行写入操作,避免文件锁拦截写入:

import pytz
# 统一定义CET时区,避免散落的时间计算出现时区错位
cet_tz = pytz.timezone("Europe/Paris")

async def create_log(self):
    today = datetime.datetime.now(cet_tz)
    date_time = today.strftime("%d_%m_%Y")
    for guild in self.bot.guilds:
        log_dir = f"./Logs/{guild.id}"
        log_path = f"{log_dir}/{date_time}.txt"
        # 自动创建缺失的目录,避免路径不存在报错
        os.makedirs(log_dir, exist_ok=True)
        # 仅当文件不存在时新建,新建后立刻关闭句柄释放锁
        if not os.path.exists(log_path):
            with open(log_path, "x", encoding="utf-8"):
                pass
            # 锁释放后再写入日志头,避免写入失败
            await self.append_new_line(
                guild.id,
                "[Time in CET][Message type][Name/ID][Channel ID]> ['Message', 'Link to attachment (if sent)' > 'New edited message (if message was edited)']\n"
            )

注意:时区处理需要安装pytz依赖,通过pip install pytz即可安装。

2. 修复日志下载命令的异常逻辑

覆盖所有可能的错误场景,给用户明确反馈,同时加空文件兜底,避免触发Discord的空文件校验规则:

@commands.command()
@commands.guild_only()
@commands.has_permissions(manage_messages=True)
async def logdownload(self, ctx, date):
    date = date.replace("/","_")
    log_path = f"./Logs/{ctx.guild.id}/{date}.txt"
    try:
        # 前置检查:文件是否存在
        if not os.path.exists(log_path):
            await ctx.send(f"未找到日期为 {date} 的日志文件,请按格式输入,例如 `28/04/2021`")
            return
        # 前置检查:文件是否为空,空文件自动加兜底内容
        if os.path.getsize(log_path) == 0:
            with open(log_path, "a+", encoding="utf-8") as f:
                f.write("当日无任何消息记录")
        logfile = discord.File(log_path)
        await ctx.send(f"已发送 {date} 对应的日志文件", file=logfile)
    except FileNotFoundError:
        await ctx.send(f"未找到日期为 {date} 的日志文件")
    except PermissionError:
        await ctx.send("Bot无权限读取日志文件,请检查服务器文件权限")
    except discord.HTTPException as e:
        await ctx.send(f"发送文件失败:{str(e)}")

3. 修复频道加入时的目录创建bug

避免目录已存在时抛错:

async def create_guild_logs(self, guildid):
    path = f"./Logs/{guildid}"
    os.makedirs(path, exist_ok=True)

4. 统一时区逻辑

把append_new_line、on_message里的时间计算全部替换成前面定义的CET时区,避免服务器本地时区和日志标注的时区错位,导致文件名和内容不匹配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 04:45:04