coPaw在Windows上运行报跨磁盘驱动器文件操作问题修复

coPaw在Windows上运行报跨磁盘驱动器文件操作问题修复

问题描述

在 Windows 上,当使用 Python 的 Path.replace() 进行原子文件写入时,如果临时文件和目标文件位于不同的磁盘驱动器,会抛出以下错误:

OSError: [WinError 17] 系统无法将文件移到不同的磁盘驱动器。

典型场景

# 原子写入模式:先写临时文件,再替换原文件
tmp_path = target_path.with_suffix(target_path.suffix + ".tmp")
tmp_path.write_text(content)
tmp_path.replace(target_path)  # 跨驱动器时失败

原因分析

  • Windows 的 MoveFileEx API 在跨卷移动时不会进行原地原子替换
  • Path.replace() 在 Windows 上依赖于这个 API,跨驱动器操作会失败
  • Linux/macOS 没有这个问题(使用 rename() 系统调用)

解决方案

使用 try-except 捕获 OSError,跨驱动器场景下回退到复制+删除:

try:
    # 尝试原子替换(同驱动器场景)
    tmp_path.replace(target_path)
except OSError:
    # 跨驱动器场景:复制后删除
    import shutil
    shutil.copy2(tmp_path, target_path)
    tmp_path.unlink()

优点

  1. 向后兼容:同驱动器场景仍使用高效的原子操作
  2. 优雅降级:跨驱动器场景自动回退到复制模式
  3. 简单可靠:不依赖额外库,标准 Python 代码

影响的文件

修复了以下 CoPaw 项目中的文件:

  1. src/copaw/app/runner/repo/json_repo.py - chats.json 读写
  2. src/copaw/app/crons/repo/json_repo.py - jobs.json 读写

类似问题

项目中可能存在相同模式的代码,建议全局搜索并统一修复:

grep -r "\.replace(" --include="*.py" src/

参考资料

  • Python pathlib.Path.replace() 文档
  • Windows MoveFileEx API 文档
posted @ 2026-03-01 15:01  枫叶流华  阅读(113)  评论(0)    收藏  举报