跳转至

Python 语言进阶 —— tempfile

介绍

tempfilePython 标准库 中的一个用于创建临时文件和临时目录的模块。该模块支持所有的平台。该模块提供了如下的高阶接口:TemporaryFileNamedTemporaryFileTemporaryDirectorySpooledTemporaryFile。 因为这些高级接口实现了 __enter____exit__ 两个特殊方法,所以它们可以和上下文管理器一同使用,用于在结束时清理这些临时文件。

同时,tempfile 模块也提供了手动清理的一些低级接口:mkstempmkdtemp

创建临时文件

tempfile 模块中可以使用 TemporaryFileNamedTemporaryFilemkstemp 创建临时文件。

TemporaryFile

TemporaryFile 的定义如下:

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

TemporaryFile 返回的是一个类文件对象,支持文件的 I/O,用于临时数据的保存。默认模式为 w+b ,表示以二进制模式读写文件。也可以设置成 w+t 模式将文本数据写入到临时文件。TemporaryFile 函数中的 prefixsuffix 可以设置文件的前缀和后缀。TemporaryFile 生成的对象可以用作上下文管理器,当完成操作后,临时文件会从系统删除。

import tempfile


def main():
    with tempfile.TemporaryFile(dir='./', prefix='test-', suffix='_txt') as tf:
        print(tf)
        print(tf.name)

        tf.write(b'Hello World')
        tf.seek(0)
        print(tf.read())


if __name__ == '__main__':
    main()

运行代码后,输出:

<tempfile._TemporaryFileWrapper object at 0x000002A1EA66CB50>
D:\Projects\Python\PythonDemos\test-32w35j6z_txt
b'Hello World'

mode 参数默认值为 w+b,写字符串时每次都需要转换成二进制写入。可以设置为 w+ 模式,这样就可以直接写入字符串类型。

NamedTemporaryFile

NamedTemporaryFile 的定义如下:

def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None,
                       newline=None, suffix=None, prefix=None,
                       dir=None, delete=True, errors=None):

NamedTemporaryFile 的用法和 TemporaryFile 完全相同,不同的是使用 NamedTemporaryFile 创建临时文件在文件系统上是可见的。可以从返回的类文件对象的 name 属性中检索该文件名。当参数 deleteTrue 时,表示一旦文件关闭就会被删除。

import os.path
import tempfile


def main():
    with tempfile.NamedTemporaryFile(dir='./', prefix='test-', suffix='_txt', delete=False) as ntf:
        ntf.write(b'Hello World')
        ntf.seek(0)
        print(ntf.read())

    print(os.path.exists(ntf.name))


if __name__ == '__main__':
    main()

运行代码后,输出;

b'Hello World'
True

SpooledTemporaryFile

SpooledTemporaryFile 的定义如下:

class SpooledTemporaryFile(_io.IOBase):
    """Temporary file wrapper, specialized to switch from BytesIO
    or StringIO to a real file when it exceeds a certain size or
    when a fileno is needed.
    """

    def __init__(self, max_size=0, mode='w+b', buffering=-1,
                 encoding=None, newline=None,
                 suffix=None, prefix=None, dir=None, errors=None):

SpooledTemporaryFile 用法与 NamedTemporaryFileTemporaryFile 基本相同。但是,SpooledTemporaryFile 会将数据缓存在内存中,直到超过 max_size 或调用文件的 fileno() 方法时,才会将数据写入到磁盘。

mktemp

Danger

mktemp 创建文件是不安全的。因为在调用 mktemp() 和随后的第一个进程尝试创建文件之间的时间内,不同的进程可能会创建一个具有此名称的文件。 解决方法是将这两个步骤结合起来,立即创建文件。自 2.3 版起已弃用: 改用 mkstemp()

mktemp 的定义如下:

def mktemp(suffix="", prefix=template, dir=None):

mktemp 函数中的参数含义如下:

  • suffix:指定临时文件名的后缀信息。
  • prefix:指定临时文件名的前缀信息。
  • dir:指定临时文件默认保存的路径。
tmp = tempfile.mktemp(dir='./')
print(tmp)

with open(tmp, 'w+') as f:  # mktemp 只生成路径,并没有生成文件,需要手动调用 open 打开文件
    f.write('hello world')
    f.seek(0)
    print(f.read())

运行代码后,输出:

./tmpi6kodjcn
hello world

mkstemp

mkstemp 的定义如下:

def mkstemp(suffix=None, prefix=None, dir=None, text=False)

mktemp 是不安全的,但是 mkstemp 是安全的。

TemporaryFile() 不同,mkstemp() 的用户负责在完成后删除临时文件。mkstemp() 返回一个包含操作系统级句柄的元组到一个打开的文件(由 os.open() 返回)和该文件的绝对路径名,系统级句柄表示的是文件的安全级别。

temp = tempfile.mkstemp()
print(temp)

fd = temp[1]
with open(fd, 'w+') as f:
    f.write('hello world')
    f.seek(0)
    print(f.read())

运行代码后,输出:

(3, 'C:\\Users\\harve\\AppData\\Local\\Temp\\tmpk01c8r2o')
hello world

创建临时目录

TemporaryDirectory

TemporaryFilemkdtemp() 一样,都是以安全的方式创建对象。TemporaryFile 生成的对象可以用作上下文管理器,完成上下文或销毁临时目录对象后,将从文件系统中删除创建的临时目录。

通过 TemporaryFile 返回对象的 name 属性获取到临时目录的名称。 当返回的对象用作上下文管理器时,name 将分配给 with 语句中 as 子句的目标。可以通过调用 cleanup() 方法显示清理目录。

mkdtemp

以最安全的方式创建临时目录。 目录的创建中没有竞争条件。 该目录只能通过创建用户 ID 进行读取、写入和搜索。mkdtemp() 的用户负责删除临时目录及其内容。

其他方法

tempfile 模块中,还提供了一些其他方法:

  1. gettempdir():返回用于临时文件的目录的名称。这定义了此模块中所有函数的 dir 参数的默认值。
  2. gettempdirb():与 gettempdir() 相同,但返回值以字节为单位。
  3. gettempprefix():返回用于创建临时文件的文件名前缀。 这不包含目录组件。
  4. gettempprefixb():与 gettempprefix() 相同,但返回值以字节为单位。
  5. tempdir():当设置为 None 以外的值时,此变量定义了此模块中定义的函数的 dir 参数的默认值。