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

以'r'和'w'模式同时打开同一文件致内容丢失问题排查

问题分析与修复:文件被清空的原因及解决办法

原代码

def repair():
  option_dict = {'1': 'Save', '2': 'Save_as', '3': 'run'}
  i = 1
  options_read = open('keybinds.options', 'r')
  options_write = open('keybinds.options', 'w', encoding='utf-8')
  for line in options_read.readlines():
    line = line.strip()
    if line.startswith(f'{option_dict[str(i)]}:'):
      i += 1
    else:
      print(f'Repairing keybind #{i} ({option_dict[str(i)]})')
      lines = options_read.readlines()
      lines[i-1] = option_dict[str(i)] + ": " + "\n"
      options_write.write(lines)
      i += 1

repair()

原文件内容

Save: <Control-s>
Save_as: <Control-o>
run: <Control-r>

问题原因

  1. 同时读写触发文件清空:用w模式打开文件时,操作系统会直接清空文件内容,此时读操作还未完成,文件已经是空的了。
  2. 文件指针到末尾导致空读:第一次调用options_read.readlines()已经读取完所有内容,文件指针移到末尾,后续再调用readlines()只会返回空列表。
  3. write()不支持直接写入列表:file.write()仅接受字符串参数,直接传列表会报错,导致逻辑无法正常执行。

修复后的代码

def repair():
    option_dict = {'1': 'Save', '2': 'Save_as', '3': 'run'}
    i = 1
    # 一次性读取所有内容到内存,自动关闭文件
    with open('keybinds.options', 'r', encoding='utf-8') as f:
        lines = f.readlines()
    
    # 遍历处理每一行
    for idx in range(len(lines)):
        line = lines[idx].strip()
        if line.startswith(f'{option_dict[str(i)]}:'):
            i += 1
        else:
            print(f'Repairing keybind #{i} ({option_dict[str(i)]})')
            lines[idx] = f'{option_dict[str(i)]}:\n'
            i += 1
    
    # 写入处理后的内容
    with open('keybinds.options', 'w', encoding='utf-8') as f:
        f.writelines(lines)

repair()

修复说明

  • 用with语句自动管理文件句柄,避免资源泄漏。
  • 先读取全部内容到内存再处理,规避文件指针偏移问题。
  • 使用writelines()直接写入列表,或拼接成字符串后用write()写入,适配文件操作要求。
  • 通过索引遍历列表,确保每一行都能被正确校验和修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:50:05