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
相关产品推荐
相关产品推荐

