Python 路径处理与文件复制:pathlib、os.path.join 与 shutil.copy

集中整理 Python 里的跨平台路径处理习惯,包括 pathlib、os.path.join 和 shutil.copy 的正确用法。

Windows、Linux、macOS 的路径分隔符并不相同,所以路径处理最容易出错的地方,往往不是复制文件本身,而是路径构造方式。

这篇文章只讲一件事:不要手工修补路径字符串,要交给 Python 的路径工具处理。

一、为什么不推荐手工拼字符串

下面这类写法不推荐:

import os

root_path = os.getcwd() + "/" + "test1.py"

或者:

import os

root_path = str(os.getcwd()).replace("\\", "/")

问题不是它们一定不能运行,而是:

  • 可读性差
  • 容易漏掉边界情况
  • 不同操作系统下不够稳
  • 完全没有必要手工处理分隔符

二、推荐做法一:优先使用 pathlib.Path

pathlib 是今天更现代、可读性更好的路径写法。

from pathlib import Path
import shutil

root_path = Path.cwd()
source = root_path / "test1.py"
target = Path("/opt/scf/test2.py")

shutil.copy(source, target)

优点:

  • 不需要自己关心 / 还是 \
  • 路径拼接更直观
  • Path 对象还能继续做存在性判断、创建目录、读取文件等操作

常见操作

from pathlib import Path

base = Path("data")
file_path = base / "reports" / "today.txt"

print(file_path.name)
print(file_path.suffix)
print(file_path.parent)
print(file_path.exists())

三、推荐做法二:使用 os.path.join

如果项目里还在使用传统标准库风格,也完全可以继续使用 os.path.join()

import os
import shutil

root_path = os.getcwd()
source = os.path.join(root_path, "test1.py")
target = os.path.join("/opt/scf", "test2.py")

shutil.copy(source, target)

它的核心价值和 Path 一样,都是把路径拼接交给标准库处理。

四、关于 shutil.copy() 的理解

shutil.copy(src, dst) 负责复制文件,但它不是“自动修复路径”的工具。

真正重要的是:

  • src 必须是正确的源路径
  • dst 必须是正确的目标路径
  • 目标目录需要提前存在
import shutil
from pathlib import Path

source = Path("data") / "input.txt"
target = Path("backup") / "input.txt"

target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy(source, target)

这里的两个关键点是:

  • Path 构造路径
  • 复制前确保目标目录已经创建

五、什么时候用 copy()copy2()copytree()

可以先这样记:

  • shutil.copy():复制文件内容和基础权限信息
  • shutil.copy2():复制文件并尽量保留元数据
  • shutil.copytree():复制整个目录树

例如复制目录:

from pathlib import Path
import shutil

source_dir = Path("static")
target_dir = Path("backup") / "static"

shutil.copytree(source_dir, target_dir, dirs_exist_ok=True)

六、几个常见误区

1. 不要依赖 replace("\\", "/")

这是“把路径当普通字符串修修补补”的典型做法,长期维护时问题很多。

2. 不要假设绝对路径在所有机器都一样

像下面这种写法,在教程里可以演示,但在真实项目里应尽量参数化或配置化:

target = Path("/opt/scf/test2.py")

更常见的是:

  • 从配置文件读取目录
  • 从环境变量读取根路径
  • 相对项目根目录构造路径

3. 复制前先确认目标目录

很多“复制失败”并不是因为 shutil.copy() 有问题,而是因为目标目录不存在。

七、实战建议

  • 新项目优先使用 pathlib.Path
  • 老项目不必强行重构到底,至少保证统一使用 os.path.join()Path
  • 路径拼接和目录创建尽量封装到小函数里
  • 文件操作前先想清楚“源文件是否存在、目标目录是否存在、是否允许覆盖”

小结

跨平台路径处理的关键,不是去记哪种系统用哪种分隔符,而是:

  • 不手工拼路径字符串
  • 不手工替换路径分隔符
  • 使用 Pathos.path.join() 构造路径

把这几个习惯养成后,文件复制和路径处理会稳定很多。

相关阅读

  • 《Python 输入输出与异常》:先掌握文件读写与 with