在Python开发中,目录与文件路径处理几乎是所有项目的刚需:读取配置、遍历文件夹、批量处理文件、日志路径配置、项目路径定位都会涉及。Python提供两套核心路径体系:os.path(函数式写法,兼容Python2/3)和pathlib(面向对象写法,Python3.4+新增)。下面按基础概念、os.path核心用法、pathlib核心用法、选型、高频避坑和批量案例进行整理。
一、路径基础:绝对路径与相对路径
绝对路径从系统根目录开始,唯一指向一个文件或目录。Windows以盘符开头,Linux/macOS以/开头。相对路径相对于当前运行脚本的工作目录,工作目录变化时会失效。跨平台分隔符方面,Windows默认使用反斜杠,Linux/macOS默认使用正斜杠。核心原则是不要手动写死路径分隔符,应通过Python内置方法自动适配,避免跨平台报错。
二、os.path模块核心操作
os.path采用函数式写法,传入路径字符串即可操作,兼容Python2/3,适合老旧项目维护。
基础路径信息获取:- import os
- test_path = 'data/test_file.txt'
- print('当前工作目录:', os.getcwd())
- abs_path = os.path.abspath(test_path)
- print('绝对路径:', abs_path)
- dir_path = os.path.dirname(abs_path)
- print('所在目录:', dir_path)
- file_name = os.path.basename(abs_path)
- print('文件名称:', file_name)
- raw_path = './data//test_file.txt'
- norm_path = os.path.normpath(raw_path)
- print('规范化路径:', norm_path)
- real_path = os.path.realpath(test_path)
- print('物理真实路径:', real_path)
复制代码
路径拼接使用os.path.join():- import os
- path1 = os.path.join('project', 'data', 'logs', 'run.log')
- print('基础拼接结果:', path1)
- path2 = os.path.join('project', '/usr/local', 'file.txt')
- print('绝对路径覆盖拼接:', path2)
- path3 = os.path.join('data', '', 'test.txt')
- print('空参数拼接:', path3)
复制代码 os.path.join()会自动适配系统分隔符,自动忽略空字符串;如果后面传入绝对路径,会覆盖前面的路径。拼接多级路径时不要首尾加分隔符,交给join方法处理。
路径类型判断与存在性校验:- import os
- test_path = 'data/test_file.txt'
- dir_path = 'data'
- print('路径是否存在:', os.path.exists(test_path))
- print('是否为文件:', os.path.isfile(test_path))
- print('是否为目录:', os.path.isdir(dir_path))
- print('是否为绝对路径:', os.path.isabs(test_path))
- print('是否为软链接:', os.path.islink(test_path))
复制代码
目录遍历os.walk():- import os
- def traverse_dir(root_path):
- for dirpath, dirnames, filenames in os.walk(root_path):
- print(f'当前遍历目录:{dirpath}')
- for dir_name in dirnames:
- print(f'子目录:{os.path.join(dirpath, dir_name)}')
- for file_name in filenames:
- file_full_path = os.path.join(dirpath, file_name)
- print(f'文件路径:{file_full_path}')
- traverse_dir('./')
复制代码 os.walk()递归遍历所有子目录和文件,返回当前目录、子目录列表、文件列表三元组。
三、pathlib模块核心操作
pathlib从Python3.4开始提供,采用面向对象写法,路径本身是Path对象,支持/运算符拼接和链式调用,代码更简洁。
Path对象初始化与拼接:- from pathlib import Path
- p1 = Path('data/test.txt')
- p2 = Path('/usr/local/python')
- p3 = Path.cwd()
- p4 = Path.home()
- print('相对路径对象:', p1)
- print('当前工作目录:', p3)
- print('用户家目录:', p4)
- base_path = Path('project')
- full_path = base_path / 'data' / 'logs' / 'run.log'
- print('路径拼接结果:', full_path)
- abs_path = Path.cwd() / 'config' / 'setting.ini'
- print('绝对拼接路径:', abs_path)
复制代码
路径属性解析与判断:- from pathlib import Path
- p = Path('data/test_image.jpg')
- print('完整路径:', p)
- print('所在父目录:', p.parent)
- print('多级父目录:', p.parents[0], p.parents[1])
- print('完整文件名(含后缀):', p.name)
- print('纯文件名(无后缀):', p.stem)
- print('文件后缀:', p.suffix)
- print('所有后缀:', p.suffixes)
- print('规范化绝对路径:', p.resolve())
- print('路径是否存在:', p.exists())
- print('是否是文件:', p.is_file())
- print('是否是目录:', p.is_dir())
- print('是否是绝对路径:', p.is_absolute())
- print('是否是软链接:', p.is_symlink())
复制代码
目录创建、删除与遍历:- from pathlib import Path
- dir_path = Path('project/logs/2026')
- dir_path.mkdir(parents=True, exist_ok=True)
- print('目录创建完成')
- root = Path('./')
- print('===== 单层目录遍历 =====')
- for item in root.iterdir():
- if item.is_file():
- print(f'文件:{item.name}')
- else:
- print(f'目录:{item.name}')
- print('===== 递归遍历所有Python文件 =====')
- for py_file in root.rglob('*.py'):
- print(f'Python文件:{py_file.resolve()}')
- for txt_file in root.glob('*.txt'):
- print(f'文本文件:{txt_file}')
复制代码 mkdir的parents=True用于递归创建多级父目录,exist_ok=True表示目录已存在时不报错。rmdir仅能删除空目录。
resolve、absolute与expanduser:- from pathlib import Path
- p = Path('documents/../file.txt')
- print(p.resolve())
- p = Path('/nonexistent/path')
- print(p.resolve(strict=False))
- p = Path('~/documents').expanduser()
- print(p)
复制代码 resolve()会解析符号链接并返回绝对路径,默认要求路径存在;strict=False在Python3.6+下路径不存在也不报错。absolute()不解析符号链接,也不要求路径存在。Path不会自动展开~,需要使用expanduser()。
Path常用属性和方法:- from pathlib import Path
- p = Path('/home/user/docs/report.txt')
- print(p.name)
- print(p.stem)
- print(p.suffix)
- print(p.suffixes)
- print(p.parent)
- print(p.parents)
- print(p.parts)
- print(p.anchor)
- print(p.as_uri())
- print(p.exists())
- print(p.is_file())
- print(p.is_dir())
- print(p.is_symlink())
- print(p.is_absolute())
- new = p.with_name('summary.txt')
- new = p.with_stem('data')
- new = p.with_suffix('.md')
- print(new)
- base = Path('/home/user')
- print(p.relative_to(base))
- content = Path('file.txt').read_text(encoding='utf-8')
- Path('out.txt').write_text('Hello', encoding='utf-8')
- data = Path('file.bin').read_bytes()
- Path('out.bin').write_bytes(data)
- Path('new_dir').mkdir(parents=True, exist_ok=True)
- Path('file.txt').unlink(missing_ok=True)
- Path('dir').rmdir()
- Path('link').symlink_to('target')
- Path('link').readlink()
复制代码 relative_to在路径不匹配时会报ValueError。
四、os.path与pathlib选型
os.path:函数式,零散繁琐,兼容Python2/3,使用os.path.join拼接,os.walk遍历。
pathlib:面向对象,链式简洁,仅Python3.4+,使用/运算符拼接,属性直接获取,iterdir/glob/rglob遍历更简洁,跨平台适配更好。
结论:新项目、Python3环境优先使用pathlib;老旧项目、需要兼容Python2时使用os.path;混合场景可以把Path对象转为字符串,兼容旧版路径函数。
五、高频场景与避坑
项目根目录精准定位:- from pathlib import Path
- FILE_PATH = Path(__file__).resolve()
- ROOT_PATH = FILE_PATH.parent
- CONFIG_PATH = ROOT_PATH / 'config' / 'setting.ini'
- print('项目根目录:', ROOT_PATH)
- print('配置文件路径:', CONFIG_PATH)
复制代码 基于脚本文件定位项目根目录,不受运行目录影响。
路径字符串与Path对象互转:- from pathlib import Path
- str_path = 'data/test.txt'
- path_obj = Path(str_path)
- new_str_path = str(path_obj)
- print('转换后字符串路径:', new_str_path)
复制代码
避坑总结:
1 禁止手动写死分隔符,不要用反斜杠或正斜杠拼接路径,交给系统方法自动适配。
2 创建多级目录必须加parents=True,否则多级嵌套目录会报错。
3 相对路径失效时用__file__定位,避免使用os.getcwd()定位项目路径,工作目录可动态切换。
4 删除目录优先判断空目录,pathlib的rmdir仅支持空目录,非空目录需要递归删除。
六、批量修改文件后缀案例- from pathlib import Path
- def batch_rename_suffix(folder_path, old_suffix, new_suffix):
- folder = Path(folder_path)
- for file in folder.rglob(f'*{old_suffix}'):
- if file.is_file():
- new_file_name = file.stem + new_suffix
- new_file_path = file.parent / new_file_name
- file.rename(new_file_path)
- print(f'修改成功:{file.name} -> {new_file_name}')
- if __name__ == '__main__':
- batch_rename_suffix('./', '.txt', '.bak')
复制代码
以上内容覆盖Python目录与文件路径处理的主要API、参数含义、调用方式和避坑点。实际开发中可根据Python版本和项目兼容要求,在os.path与pathlib之间选择。 |