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

discord.py文件追加异常:追加模式下却覆盖原有内容

Discord.py 临时语音频道文件读写问题修复

问题概述

开发discord.py机器人时遇到两个核心问题:

  • 触发on_voice_state_update事件,用户加入指定语音频道(ID:1059553884286230608)创建临时频道后,使用追加模式("a")写入member_channel.txt时,文件原有内容被清空,而非追加新内容。
  • 临时语音频道为空时,删除频道并同步删除文件对应行的逻辑存在错误,无法正确更新文件内容。

问题分析与修复

1. 追加写入异常问题

原代码中写入逻辑的语法本身无错误,但存在两个潜在问题:

  • 删除逻辑中错误使用w+模式的时机,可能覆盖文件内容
  • 代码中的HTML转义字符(如"、 )导致实际运行时文件操作异常

修复方案:

  • 移除HTML转义符,使用标准字符串格式
  • 确保追加模式的文件操作独立执行,避免被其他逻辑干扰

2. 空频道删除与文件行删除逻辑问题

原删除逻辑存在多处错误:

  • 多层循环嵌套混乱,遍历逻辑逻辑冲突
  • 修改列表的同时进行遍历,引发索引异常
  • 文件内容拼接逻辑错误,导致格式混乱
  • 依赖全局变量member_channel,无法正确指向当前要删除的频道
  • 冗余的文件关闭操作(with语句会自动关闭文件)

修正后的完整代码

@bot.event
async def on_voice_state_update(member, before, after):
    # 处理用户加入指定频道,创建临时语音频道
    if after.channel is not None and after.channel.id == 1059553884286230608:
        guild = bot.get_guild(966749409314504774)
        everyone_role = discord.utils.get(guild.roles, id=966749409314504774)
        community_role = discord.utils.get(guild.roles, id=1006304076331483256)
        muted_role = discord.utils.get(guild.roles, id=1059109986258653244)
        
        # 创建临时频道并设置权限
        member_channel = await guild.create_voice_channel(name=f"Vocal de {member.name}")
        target_category = discord.utils.get(guild.channels, id=1057730051321372692)
        await member_channel.edit(category=target_category)
        
        await member_channel.set_permissions(member, connect=True, manage_channels=True, manage_permissions=True, priority_speaker=True, move_members=True)
        await member_channel.set_permissions(everyone_role, view_channel=False)
        await member_channel.set_permissions(community_role, view_channel=True)
        await member_channel.set_permissions(muted_role, speak=False)
        
        await member.move_to(member_channel)
        
        # 追加写入文件(修复转义符问题)
        with open("member_channel.txt", "a", encoding="utf-8") as file:
            file.write(f"{member.id}:{member_channel.id}\n")
        print(f"[{await get_hour()}] {member.name} 创建了临时语音频道。")

    # 处理空临时频道的删除与文件内容更新
    elif before.channel is not None and len(before.channel.members) == 0:
        channel_id = str(before.channel.id)
        updated_lines = []
        
        try:
            # 读取文件并筛选保留的行
            with open("member_channel.txt", "r", encoding="utf-8") as file:
                for line in file:
                    line = line.strip()
                    if not line:
                        continue
                    # 检查当前行是否对应要删除的频道
                    if channel_id not in line.split(":"):
                        updated_lines.append(line)
            
            # 删除空频道
            await before.channel.delete()
            
            # 写入更新后的内容
            with open("member_channel.txt", "w", encoding="utf-8") as file:
                file.write("\n".join(updated_lines) + "\n")
            
            print(f"[{await get_hour()}] 已删除临时语音频道 {before.channel.name}。")
            
        except Exception as e:
            print(f"删除频道或更新文件时出错: {e}")
            return

关键修复点说明

  • 文件操作:统一指定encoding="utf-8"避免编码问题,使用with语句自动管理文件关闭,移除冗余的file.close()
  • 追加写入:使用f-string简化字符串拼接,确保换行符\n正确
  • 删除逻辑:
    • 先读取所有行,筛选出不需要删除的内容后再写入文件,避免遍历同时修改列表的问题
    • 直接使用before.channel获取要删除的频道,无需依赖全局变量
    • 增加异常捕获,便于排查错误
    • 跳过空行,保持文件内容整洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:21:47