# 自动化脚本的临时文件别乱放：用 tempfile 隔离中间产物并保证清理

## 文档明确的机制

报表转换、下载解压或调用外部命令时，脚本常需要一个“过程中才存在”的文件或目录。Python 标准库 `tempfile` 的用途正是生成临时文件和临时目录，并可在所有受支持平台工作。文档把接口分为两层：`TemporaryFile`、`NamedTemporaryFile`、`TemporaryDirectory`、`SpooledTemporaryFile` 是高级接口，可自动清理，也能作为上下文管理器；`mkstemp()` 和 `mkdtemp()` 是低层函数，需要使用者手动清理。

`TemporaryFile()` 返回可作为临时存储的文件类对象，默认模式是 `'w+b'`，无需先关闭即可读写；文件关闭后会被销毁，包括对象被垃圾回收时的隐式关闭。要注意，它在 Unix 下可能根本没有目录项，或创建后立即移除目录项；其他平台不一定支持这种行为。因此，文档明确提醒：代码不应依赖 `TemporaryFile()` 创建的文件“有”或“没有”文件系统中的可见名称。若需要把文件名传给后续步骤，应使用 `NamedTemporaryFile()`，它保证文件在文件系统中有可见名，路径可从 `name` 属性取得。

`NamedTemporaryFile()` 同样可用 `with` 管理，并通过 `delete`、`delete_on_close` 控制删除时机：二者默认均为 `True`，文件关闭时删除；若 `delete=True` 且 `delete_on_close=False`，则在上下文管理器退出或对象终结时删除，但文档也说明这种情况下删除并不总是有保证；若 `delete=False`，`delete_on_close` 会被忽略。文档建议，在 `with` 中关闭后还要按名称重新打开文件时，把 `delete_on_close=False`，这样上下文退出时仍可获得自动清理协助。

需要容纳解压结果、多个中间片段或外部命令产物时，`TemporaryDirectory` 更合适。它安全创建目录，可作为上下文管理器；上下文结束或对象销毁时，新创建的目录及其全部内容都会被移除。目录名在 `name` 属性中，也可以主动调用 `cleanup()`。`delete=False` 可禁用退出上下文时对目录树的清理；文档说明，这在调试期间，或需要根据其他逻辑条件决定清理行为时可能有用。

这些接口都支持通过 `dir`、`prefix`、`suffix` 控制位置和名称。随机字符用于在共享临时目录中安全创建文件。由于参数顺序为兼容旧行为而略显特殊，文档建议使用关键字参数。若使用 `mkstemp()`，它会返回操作系统级文件句柄和绝对路径；调用者必须负责用 `os.close()` 关闭句柄，并用 `os.remove()` 删除文件。`mkdtemp()` 则返回新目录绝对路径，调用者负责删除目录及其内容。

## 团队自行约定的接手建议

**以下是团队接手自动化脚本时的约定，不是 Python 文档额外承诺的产品能力。**

第一，默认优先选择高级接口和上下文管理器：单个匿名中间流用 `TemporaryFile`；必须向外部命令传路径时用 `NamedTemporaryFile`；下载包、解压目录或一批中间文件用 `TemporaryDirectory`。只有在已有流程必须持有底层句柄或路径时，才使用 `mkstemp()`、`mkdtemp()`，并在代码审查中明确关闭与删除责任。

第二，把临时位置、前缀和后缀写成显式参数。接手者可通过 `prefix` 识别任务来源，通过 `dir` 把中间产物限制在团队确认可写、可清理的位置；不要依赖当前工作目录，也不要通过修改全局 `tempfile.tempdir` 影响其他代码。需要传给外部命令时，团队应把生成的路径视为普通字符串处理，因为文档说明无法保证文件名具备“不需要引号”等良好属性。

第三，代码评审时禁止使用 `mktemp()`。文档已标明它自 Python 2.3 起弃用；它只返回当时不存在的名称，在程序随后创建文件前，其他进程可能抢先创建同名文件，形成竞态安全问题。需要手动管理生命周期时，应改用 `mkstemp()`，或按文档示例用 `NamedTemporaryFile(delete=False)` 并自行 `os.unlink()`。

## 边界与总结

自动清理不是所有异常终止场景下的绝对保证。文档明确说明，在 POSIX 上，被 `SIGKILL` 突然终止的进程无法自动删除它创建的 `NamedTemporaryFile`。因此，团队不能把上下文管理器理解为所有被杀任务后的兜底清扫机制；任务编排层仍应能识别残留目录并安排人工或已有运维流程处理。

Windows 差异也要单独看待。重新按名称打开仍处于打开状态的临时文件时，Windows 需要满足 `delete=False`、额外打开共享删除访问，或 `delete=True` 且 `delete_on_close=False` 等条件；若额外打开的对象未在退出上下文前关闭，退出时的 `os.unlink()` 可能引发 `PermissionError`。当 `delete_on_close=False` 且用户对目录没有删除权限时，退出时同样可能失败。`TemporaryDirectory(ignore_cleanup_errors=True)` 可按文档以“尽力而为”方式忽略清理异常，但这不是权限问题的修复。

综上，`tempfile` 已提供从匿名文件、命名文件到临时目录的分层机制。自动化脚本应优先让上下文管理器承担常规关闭与清理，低层函数则把责任写清楚；同时保留对强杀进程、Windows 权限和手动清理失败的边界意识。

## 相关工具

[AI 工作流 ROI 诊断器](/demos/ai-workflow-roi-diagnostic/index.html) · 查看工具的输入要求、输出说明与适用范围。


来源：[自动化脚本的临时文件别乱放：用 tempfile 隔离中间产物并保证清理](https://docs.python.org/3/library/tempfile.html)
