tmp_path 能自动清理是因为它是 pytest 函数级固件,每次测试创建唯一空目录,退出时自动调用 shutil.rmtree() 删除;作用域为 function,返回 pathlib.path,无需手动 teardown,但不清理同级手动创建路径。

直接用 tmp_path 固件,别自己调用 tempfile.mkdtemp() —— 后者不自动清理,且极易在 CI 或本地反复运行时堆积 pytest-* 目录。
为什么 tmp_path 能自动删干净
tmp_path 是 pytest 内置的函数级固件,每次测试运行都会创建一个全新的 pathlib.Path 实例,指向系统临时目录下唯一、空的子目录(如 /tmp/pytest-of-user/pytest-123/)。测试函数退出后(无论 pass 还是 fail),pytest 自动执行 shutil.rmtree(),递归删除整个目录。
- 作用域严格限定为
function,多个测试之间完全隔离 - 返回值是
pathlib.Path,支持/拼接、.write_text()、.mkdir(exist_ok=True)等现代写法 - 不依赖
try/finally或yield,声明即生效,无额外 teardown 代码 - 它不清理你手动创建的同级路径(比如
tempfile.gettempdir() / "my-test-dir"),只管自己生成的那个目录
常见错误:手动生成临时路径还忘了删
典型表现是测试跑完后磁盘上残留大量 pytest-* 目录,尤其在 CI 环境或本地反复调试时。这不是 bug,而是因为你绕过了 pytest 生命周期管理。
- 错用
tempfile.mktemp():已弃用,且返回字符串,容易引发路径拼接错误 - 用
tempfile.mkdtemp()但没配shutil.rmtree():一旦测试异常退出或被 Ctrl+C 中断,目录就永远留在磁盘上 - 把
tmp_path赋值给模块变量或全局变量:超出当前测试生命周期后引用会失效,甚至导致后续测试误用旧路径 - 显式调用
.remove()或shutil.rmtree(tmp_path):多余,且可能在 pytest 清理阶段触发FileNotFoundError
需要保留临时文件时怎么临时禁用清理
调试时想看中间生成的文件?可以临时“劫持” tmp_path,但必须显式移出 pytest 管理范围。
- 加命令行选项:
pytest --keep-tmp(需在conftest.py中注册该选项) - 在测试中判断:
if request.config.getoption("--keep-tmp", default=False): - 用
shutil.move()或shutil.copytree()把目标子目录复制到项目外固定路径(如debug_artifacts/),再让 pytest 正常清理原tmp_path - 切勿直接
os.rename(tmp_path, ...):可能跨文件系统失败;也别改权限硬留着,会干扰下次测试
什么时候该换用 tmp_path_factory
tmp_path 够用,除非你遇到这两个明确场景:
- 需要在
session或module级固件里创建临时路径(比如启动一次数据库服务,多个测试共用同一数据目录) - 想为不同测试生成可预测的路径名(例如固定后缀:
tmp_path_factory.mktemp("test-db", numbered=True)) - 注意:
tmp_path_factory不自动清理,你得自己在teardown阶段调用shutil.rmtree(),否则照样堆积
最易被忽略的一点:tmp_path 的清理行为只对它自己创建的目录生效;如果你在测试里又调用了第三方库(比如 requests-cache 或某个 CLI 工具),它们写的临时文件不会被连带清理——得单独查文档看是否支持配置缓存路径,再把它也指向 tmp_path 下的子目录。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











