tempfile — 生成临时文件和目录

源代码: Lib/tempfile.py


此模块创建临时文件和目录。它适用于所有支持的平台。 TemporaryFileNamedTemporaryFileTemporaryDirectorySpooledTemporaryFile 是高级接口,它们提供自动清理功能,并且可以用作 上下文管理器mkstemp()mkdtemp() 是低级函数,需要手动清理。

所有用户可调用的函数和构造函数都接受额外的参数,这些参数允许直接控制临时文件和目录的位置和名称。此模块使用的文件名包含一个随机字符字符串,允许在共享临时目录中安全地创建这些文件。为了保持向后兼容性,参数顺序有些奇怪;建议使用关键字参数以提高清晰度。

该模块定义了以下用户可调用的项目

tempfile.TemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)

返回一个 类文件对象,可以用作临时存储区域。该文件是使用与 mkstemp() 相同的规则安全创建的。它将在关闭后立即销毁(包括在对象被垃圾回收时隐式关闭)。在 Unix 下,文件的目录条目要么根本不创建,要么在文件创建后立即删除。其他平台不支持此功能;您的代码不应依赖于使用此函数创建的临时文件在文件系统中是否具有可见名称。

生成的对象可以用作 上下文管理器(请参阅 示例)。在上下文完成或文件对象销毁时,临时文件将从文件系统中删除。

mode 参数默认为 'w+b',以便创建的文件可以在不关闭的情况下进行读写。使用二进制模式是为了使其在所有平台上表现一致,而无需考虑存储的数据。 bufferingencodingerrorsnewline 的解释方式与 open() 相同。

dirprefixsuffix 参数的含义和默认值与 mkstemp() 相同。

返回的对象在 POSIX 平台上是一个真正的文件对象。在其他平台上,它是一个类文件对象,其 file 属性是底层的真正文件对象。

如果 os.O_TMPFILE 标志可用且有效(特定于 Linux,需要 Linux 内核 3.11 或更高版本),则使用该标志。

在既不是 Posix 也不是 Cygwin 的平台上,TemporaryFile 是 NamedTemporaryFile 的别名。

引发带有参数 fullpath审计事件 tempfile.mkstemp

版本 3.5 中的变化: 现在如果可用,则使用 os.O_TMPFILE 标志。

版本 3.8 中的变化: 添加了 errors 参数。

tempfile.NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True, *, errors=None, delete_on_close=True)

此函数的操作与 TemporaryFile() 完全相同,但以下区别除外

  • 此函数返回的文件保证在文件系统中具有可见名称。

  • 为了管理命名文件,它使用 deletedelete_on_close 参数扩展了 TemporaryFile() 的参数,这些参数确定是否以及如何自动删除命名文件。

返回的对象始终是一个 类文件对象,其 file 属性是底层的真正文件对象。此类文件对象可以在 with 语句中使用,就像普通文件一样。可以从返回的类文件对象的 name 属性中检索临时文件的名称。在 Unix 上,与 TemporaryFile() 不同,目录条目不会在文件创建后立即取消链接。

如果 *delete* 为 true(默认值)且 *delete_on_close* 为 true(默认值),则文件将在关闭后立即删除。如果 *delete* 为 true 且 *delete_on_close* 为 false,则仅在上下文管理器退出时或 类文件对象 被终结时才会删除文件。在这种情况下,不能保证一定会删除文件(请参阅 object.__del__())。如果 *delete* 为 false,则 *delete_on_close* 的值将被忽略。

因此,要使用临时文件名在关闭后重新打开文件,请确保在关闭时不要删除文件(将 *delete* 参数设置为 false),或者,如果在 with 语句中创建了临时文件,请将 *delete_on_close* 参数设置为 false。建议使用后一种方法,因为它可以在上下文管理器退出时自动清理临时文件。

在临时文件仍处于打开状态时,通过其名称再次打开该文件的工作方式如下

  • 在 POSIX 上,始终可以再次打开该文件。

  • 在 Windows 上,请确保满足以下至少一项条件

    • *delete* 为 false

    • 其他打开操作共享删除访问权限(例如,通过使用标志 O_TEMPORARY 调用 os.open()

    • *delete* 为 true,但 *delete_on_close* 为 false。请注意,在这种情况下,不共享删除访问权限的其他打开操作(例如,通过内置函数 open() 创建)必须在退出上下文管理器之前关闭,否则上下文管理器退出时对 os.unlink() 的调用将失败并引发 PermissionError

在 Windows 上,如果 *delete_on_close* 为 false,并且在用户缺少删除访问权限的目录中创建了文件,则在退出上下文管理器时对 os.unlink() 的调用将失败并引发 PermissionError。当 *delete_on_close* 为 true 时,不会发生这种情况,因为打开操作会请求删除访问权限,如果未授予请求的访问权限,则打开操作会立即失败。

在 POSIX(仅限)上,使用 SIGKILL 突然终止的进程无法自动删除其创建的任何 NamedTemporaryFile。

引发带有参数 fullpath审计事件 tempfile.mkstemp

版本 3.8 中的变化: 添加了 errors 参数。

在 3.12 版更改: 添加了 *delete_on_close* 参数。

class tempfile.SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)

此类的操作与 TemporaryFile() 完全相同,不同之处在于数据会缓存在内存中,直到文件大小超过 *max_size* 或调用文件的 fileno() 方法,此时内容将写入磁盘,并且操作将像使用 TemporaryFile() 一样继续进行。

rollover()

生成的文件有一个额外的方法 rollover(),该方法会导致文件滚动到磁盘文件,而不管其大小如何。

返回的对象是一个类文件对象,其 _file 属性是 io.BytesIOio.TextIOWrapper 对象(取决于指定的是二进制模式还是文本模式),还是真正的文件对象,具体取决于是否已调用 rollover()。此类文件对象可以在 with 语句中使用,就像普通文件一样。

在 3.3 版更改: truncate 方法现在接受 *size* 参数。

版本 3.8 中的变化: 添加了 errors 参数。

在 3.11 版更改: 完全实现了 io.BufferedIOBaseio.TextIOBase 抽象基类(取决于指定的是二进制模式还是文本模式)。

class tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False, *, delete=True)

此类使用与 mkdtemp() 相同的规则安全地创建临时目录。生成的对象可以用作 上下文管理器(请参阅 示例)。在上下文完成或临时目录对象销毁时,将从文件系统中删除新创建的临时目录及其所有内容。

name

可以从返回对象的 name 属性中检索目录名称。当返回的对象用作 上下文管理器 时,name 将被赋值给 with 语句中 as 子句的目标(如果有)。

cleanup()

可以通过调用 cleanup() 方法显式清理目录。如果 *ignore_cleanup_errors* 为 true,则在显式或隐式清理期间发生的任何未处理异常(例如在 Windows 上删除打开文件时的 PermissionError)都将被忽略,并且剩余的可删除项目将被“尽力”删除。否则,将在发生清理的任何上下文中引发错误(cleanup() 调用、退出上下文管理器、对象被垃圾回收或解释器关闭时)。

*delete* 参数可用于在退出上下文时禁用对目录树的清理。虽然上下文管理器禁用退出上下文时执行的操作似乎很不寻常,但在调试期间或当您需要根据其他逻辑条件执行清理行为时,这非常有用。

使用参数 fullpath 引发 审计事件 tempfile.mkdtemp

3.2 版新增。

3.10 版更改: 添加了 *ignore_cleanup_errors* 参数。

3.12 版更改: 添加了 *delete* 参数。

tempfile.mkstemp(suffix=None, prefix=None, dir=None, text=False)

以最安全的方式创建临时文件。假设平台为 os.open() 正确实现了 os.O_EXCL 标志,则在文件创建过程中不存在竞争条件。该文件只能由创建用户 ID 读取和写入。如果平台使用权限位来指示文件是否可执行,则该文件对任何人都不可执行。文件描述符不会被子进程继承。

TemporaryFile() 不同,mkstemp() 的用户负责在使用完临时文件后将其删除。

如果 *suffix* 不是 None,则文件名将以该后缀结尾,否则将没有后缀。mkstemp() 不会在文件名和后缀之间放置点;如果您需要点,请将其放在 *suffix* 的开头。

如果 *prefix* 不是 None,则文件名将以该前缀开头;否则,将使用默认前缀。默认值是 gettempprefix()gettempprefixb() 的返回值(视情况而定)。

如果 *dir* 不是 None,则将在该目录中创建文件;否则,将使用默认目录。默认目录是从平台相关的列表中选择的,但应用程序的用户可以通过设置 *TMPDIR*、*TEMP* 或 *TMP* 环境变量来控制目录位置。因此,不能保证生成的文件名具有任何良好的属性,例如在通过 os.popen() 传递给外部命令时不需要引用。

如果 *suffix*、*prefix* 和 *dir* 中的任何一个不是 None,则它们必须是相同的类型。如果它们是字节,则返回的名称将是字节而不是字符串。如果要在默认行为下强制返回字节值,请传递 suffix=b''

如果指定了 *text* 并且为 true,则以文本模式打开文件。否则(默认情况下),以二进制模式打开文件。

mkstemp() 返回一个元组,其中包含打开文件的操作系统级句柄(如 os.open() 返回的那样)和该文件的绝对路径名,顺序依次为。

引发带有参数 fullpath审计事件 tempfile.mkstemp

3.5 版更改: 现在可以以字节形式提供 *suffix*、*prefix* 和 *dir*,以便获得字节返回值。在此之前,只允许使用字符串。*suffix* 和 *prefix* 现在接受并默认为 None,以便使用适当的默认值。

3.6 版更改: *dir* 参数现在接受 类路径对象

tempfile.mkdtemp(suffix=None, prefix=None, dir=None)

以最安全的方式创建临时目录。在目录创建过程中不存在竞争条件。该目录只能由创建用户 ID 读取、写入和搜索。

mkdtemp() 的用户负责在使用完临时目录及其内容后将其删除。

*prefix*、*suffix* 和 *dir* 参数与 mkstemp() 相同。

mkdtemp() 返回新目录的绝对路径名。

使用参数 fullpath 引发 审计事件 tempfile.mkdtemp

3.5 版更改: 现在可以以字节形式提供 *suffix*、*prefix* 和 *dir*,以便获得字节返回值。在此之前,只允许使用字符串。*suffix* 和 *prefix* 现在接受并默认为 None,以便使用适当的默认值。

3.6 版更改: *dir* 参数现在接受 类路径对象

3.12 版更改: 即使 *dir* 是相对的,mkdtemp() 现在也始终返回绝对路径。

tempfile.gettempdir()

返回用于临时文件的目录名称。这定义了此模块中所有函数的 *dir* 参数的默认值。

Python 搜索标准目录列表,以查找调用用户可以在其中创建文件的目录。该列表为:

  1. TMPDIR 环境变量命名的目录。

  2. TEMP 环境变量命名的目录。

  3. TMP 环境变量命名的目录。

  4. 特定于平台的位置

    • 在 Windows 上,依次为目录 C:\TEMPC:\TMP\TEMP\TMP

    • 在所有其他平台上,将按顺序搜索以下目录:/tmp/var/tmp/usr/tmp

  5. 最后,将使用当前工作目录。

此搜索的结果会被缓存,请参阅下文对 tempdir 的描述。

在 3.10 版更改: 始终返回字符串。以前,只要 tempdir 值不为 None,它就会返回任何类型的 tempdir 值。

tempfile.gettempdirb()

gettempdir() 相同,但返回值为字节串。

3.5 版新增。

tempfile.gettempprefix()

返回用于创建临时文件的文件名前缀。这不包含目录部分。

tempfile.gettempprefixb()

gettempprefix() 相同,但返回值为字节串。

3.5 版新增。

该模块使用一个全局变量来存储 gettempdir() 返回的用于临时文件的目录名称。可以直接设置它来覆盖选择过程,但不建议这样做。此模块中的所有函数都接受一个 dir 参数,该参数可用于指定目录。这是推荐的方法,它不会通过更改全局 API 行为来影响其他代码。

tempfile.tempdir

当设置为非 None 的值时,此变量定义此模块中定义的函数的 dir 参数的默认值,包括其类型,字节串或字符串。它不能是 类路径对象

如果在调用除 gettempprefix() 之外的任何上述函数时,tempdirNone(默认值),则将按照 gettempdir() 中描述的算法对其进行初始化。

注意

请注意,如果将 tempdir 设置为字节串值,则会产生一个副作用:当没有提供显式的字符串类型的 prefixsuffixdir 参数时,mkstemp()mkdtemp() 的全局默认返回类型将更改为字节串。请不要编写期望或依赖于此行为的代码。为了与历史实现兼容,保留了这种尴尬的行为。

示例

以下是一些 tempfile 模块的典型用法示例

>>> import tempfile

# create a temporary file and write some data to it
>>> fp = tempfile.TemporaryFile()
>>> fp.write(b'Hello world!')
# read data from file
>>> fp.seek(0)
>>> fp.read()
b'Hello world!'
# close the file, it will be removed
>>> fp.close()

# create a temporary file using a context manager
>>> with tempfile.TemporaryFile() as fp:
...     fp.write(b'Hello world!')
...     fp.seek(0)
...     fp.read()
b'Hello world!'
>>>
# file is now closed and removed

# create a temporary file using a context manager
# close the file, use the name to open the file again
>>> with tempfile.NamedTemporaryFile(delete_on_close=False) as fp:
...     fp.write(b'Hello world!')
...     fp.close()
... # the file is closed, but not removed
... # open the file again by using its name
...     with open(fp.name, mode='rb') as f:
...         f.read()
b'Hello world!'
>>>
# file is now removed

# create a temporary directory using the context manager
>>> with tempfile.TemporaryDirectory() as tmpdirname:
...     print('created temporary directory', tmpdirname)
>>>
# directory and contents have been removed

已弃用的函数和变量

创建临时文件的一种历史方法是首先使用 mktemp() 函数生成文件名,然后使用此名称创建文件。不幸的是,这并不安全,因为在调用 mktemp() 和第一个进程随后尝试创建文件之间的时间内,另一个进程可能会使用此名称创建文件。解决方案是将这两个步骤结合起来,立即创建文件。 mkstemp() 和上述其他函数都使用这种方法。

tempfile.mktemp(suffix='', prefix='tmp', dir=None)

2.3 版后已移除: 请改用 mkstemp()

返回在调用时不存在的文件的绝对路径名。 prefixsuffixdir 参数与 mkstemp() 的参数类似,但不支持字节串文件名、suffix=Noneprefix=None

警告

使用此函数可能会在程序中引入安全漏洞。当你准备对它返回的文件名执行任何操作时,其他人可能已经捷足先登了。可以通过 NamedTemporaryFile() 轻松替换 mktemp() 的使用,并向其传递 delete=False 参数

>>> f = NamedTemporaryFile(delete=False)
>>> f.name
'/tmp/tmptjujjt'
>>> f.write(b"Hello World!\n")
13
>>> f.close()
>>> os.unlink(f.name)
>>> os.path.exists(f.name)
False