文章
合集Python 语言基础第 20 / 21 篇

路径处理与跨平台兼容

背景

Windows 使用反斜杠 \ 作为路径分隔符,Unix/Linux/macOS 使用正斜杠 /。直接用字符串硬编码路径会导致代码在另一平台失效。Python 提供了两种标准解决方案。

将路径视为 Path 对象而非字符串,是跨平台路径处理的核心原则

现代方案:pathlib(Python 3.6+ 推荐)

pathlib 以面向对象的方式处理路径,自动适配当前平台的分隔符。

路径构建

from pathlib import Path

# 用 / 运算符拼接路径,无需手动处理分隔符
config_path = Path('data') / '2024' / 'config.txt'

# Windows 输出:data\2024\config.txt
# Linux/macOS 输出:data/2024/config.txt
print(config_path)

# 混用分隔符的输入也会自动规范化
messy_path = Path('data\\2024/config.txt')
print(messy_path)   # 统一为当前平台格式

常用属性与方法

p = Path('data') / '2024' / 'report.txt'

print(p.exists())       # 路径是否存在
print(p.is_file())      # 是否是文件
print(p.is_dir())       # 是否是目录
print(p.parent)         # 父目录:data/2024
print(p.name)           # 文件名:report.txt
print(p.stem)           # 无后缀名:report
print(p.suffix)         # 后缀:.txt
print(p.suffixes)       # 所有后缀列表:['.txt']
print(p.absolute())     # 绝对路径
print(p.resolve())      # 解析符号链接后的绝对路径

文件读写

# 直接读写文本,无需手动 open()
content = Path('notes.txt').read_text(encoding='utf-8')
Path('output.txt').write_text('Hello World', encoding='utf-8')

# 读写二进制
img_bytes = Path('photo.jpg').read_bytes()
Path('copy.jpg').write_bytes(img_bytes)

目录操作

# 创建目录(含中间层,已存在时不报错)
Path('logs/2024/04').mkdir(parents=True, exist_ok=True)

# 递归查找所有 .txt 文件
for txt_file in Path('data').rglob('*.txt'):
    print(txt_file)

# 列出直接子项
for item in Path('.').iterdir():
    print(item)

实际应用示例

from pathlib import Path

def read_project_config(project_name):
    base_dir = Path.home() / 'projects' / project_name / 'config'
    config_file = base_dir / 'config.json'

    base_dir.mkdir(parents=True, exist_ok=True)

    if config_file.exists():
        return config_file.read_text(encoding='utf-8')
    return None

传统方案:os.path(兼容旧代码)

import os

path = os.path.join('data', '2024', 'config.txt')
# Windows: data\2024\config.txt
# Linux:   data/2024/config.txt

print(os.path.exists(path))
print(os.path.isfile(path))
print(os.path.isdir(path))
print(os.path.dirname(path))    # 父目录
print(os.path.basename(path))   # 文件名
print(os.path.splitext(path))   # ('data/2024/config', '.txt')
print(os.path.abspath(path))    # 绝对路径

错误示范

# 硬编码反斜杠:在 Linux/macOS 上失效
path = 'data\\2024\\config.txt'   # Linux 将此视为包含反斜杠的单一文件名

# 字符串拼接:不可移植
path = 'data' + '\\' + 'config.txt'

# 推荐写法
path = Path('data') / 'config.txt'
path = os.path.join('data', 'config.txt')

特殊情况

1. 正则表达式匹配路径

在 Windows 上,str(path) 得到含反斜杠的字符串,而反斜杠在正则中是转义符,会干扰匹配。使用 as_posix() 强制正斜杠格式:

import re
from pathlib import Path

path = Path('data/2024/file.txt')
posix_path = path.as_posix()   # 始终输出:data/2024/file.txt
re.match(r'data/\d+/.*', posix_path)

2. 命令行参数传入路径

import sys
from pathlib import Path

input_path = Path(sys.argv[1])
# Path 构造时自动规范化,无需关心输入的分隔符方向

3. 原始字符串(r"")的作用范围

# r"" 只防止 Python 将 \ 解释为转义符,不等于跨平台
win_path = r'data\2024\config.txt'   # Windows 可用,Linux 失效

# 跨平台始终用 pathlib
cross_platform = Path('data') / '2024' / 'config.txt'

Windows 对正斜杠的支持

Windows NTFS 文件系统底层同时接受 / 和 \,因此以下写法在 Windows 上均可工作:

open('data\\example.txt', 'w')   # 标准 Windows 写法
open('data/example.txt', 'w')    # Unix 风格(Windows 同样识别)
open(r'data\example.txt', 'w')   # 原始字符串写法

但存在两个隐患:

隐患 1:转义字符错误

# \n 被 Python 解释为换行,\t 为制表符
open('data\new_folder\test.txt', 'w')
# 实际路径:data<换行符>ew_folder<制表符>est.txt

# 正确写法
open('data\\new_folder\\test.txt', 'w')   # 双反斜杠
open(r'data\new_folder\test.txt', 'w')    # 原始字符串
open('data/new_folder/test.txt', 'w')     # 正斜杠

隐患 2:移植到 Linux/macOS 时失效

反斜杠在 Linux/macOS 不是路径分隔符,'data\\new_folder\\test.txt' 会被视为包含反斜杠字符的单个文件名,而非目录结构。

总结:跨平台路径最佳实践

场景推荐避免
拼接路径Path('a') / 'b''a\\b' 或字符串拼接
获取家目录Path.home()os.environ['HOME'](Linux 专用)
临时文件目录tempfile.gettempdir()硬编码 /tmp 或 C:\Temp
相对路径转绝对路径path.resolve()手动拼接 os.getcwd()
网络 URL 或正则匹配路径path.as_posix()str(path)(Windows 含反斜杠)