
Python 3 提供了 open() 的 'x'(exclusive creation)模式,可确保目标文件不存在时才创建并写入,从根本上规避竞态条件与意外覆盖,是实现“不覆盖复制”的最简洁、原生、线程安全方案。
python 3 提供了 open() 的 'x'(exclusive creation)模式,可确保目标文件不存在时才创建并写入,从根本上规避竞态条件与意外覆盖,是实现“不覆盖复制”的最简洁、原生、线程安全方案。
在实际开发中,尤其在多进程、定时任务或并发文件操作场景下,使用 shutil.copy() 或 shutil.copy2() 直接复制文件存在固有风险:它们默认会静默覆盖已存在的目标文件,且无内置参数禁用该行为。更关键的是,像以下常见写法存在经典竞态条件(race condition):
if not os.path.exists(destfile): # ✅ 检查存在性
shutil.copy(srcfile, destfile) # ❌ 但检查与复制之间存在时间窗口
在此间隙中,若另一进程/线程创建了同名文件,shutil.copy() 将直接覆盖它——这不仅破坏数据一致性,还可能引发权限异常或业务逻辑错误。
✅ 正确解法:利用 Python 3.3+ 引入的 'x' 打开模式(exclusive creation)。该模式要求目标路径必须完全不存在,否则立即抛出 FileExistsError,且整个打开+写入过程由操作系统原子保证,彻底消除竞态风险。
以下是推荐的安全复制函数:
def safe_copy(srcfile: str, destfile: str) -> None:
"""
安全复制文件:仅当 destfile 不存在时成功;否则抛出 FileExistsError。
支持二进制文件(如图片、PDF、日志等),保留原始内容完整性。
"""
with open(srcfile, "rb") as src, open(destfile, "wxb") as dest:
# "wxb" = write + binary + exclusive → 确保目标不存在且以二进制写入
dest.write(src.read())
⚠️ 注意事项:
-
"wxb"中的x是核心:它启用独占创建,b确保二进制安全(避免文本换行符转换); - 不依赖
shutil,无需额外权限检查或目录预创建(但需确保目标父目录存在,否则open()报FileNotFoundError); - 若需自动创建目标目录,可前置调用
os.makedirs(os.path.dirname(destfile), exist_ok=True); - 此方法不复制文件元数据(如修改时间、权限位);如需保留,须先用
shutil.copy2()复制,再通过os.replace()原子替换(但会丢失“不覆盖”语义)——因此,纯“不覆盖”需求下,'x'模式是唯一推荐方案。
? 进阶提示:对于大文件,为避免内存压力,建议流式读写:
def safe_copy_streamed(srcfile: str, destfile: str, buffer_size: int = 8192) -> None:
with open(srcfile, "rb") as src, open(destfile, "wxb") as dest:
while chunk := src.read(buffer_size):
dest.write(chunk)
综上,Python 3 原生支持无覆盖文件复制——无需第三方库、不引入竞态、语义清晰明确。牢记:要用 'x',不要用 'w' 或 'a';要信任 OS 的原子创建,而非应用层的 exists() 判断。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











