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

