# `tempfile` --- 生成臨時檔案和目錄

原始碼：Lib/tempfile.py

该模块可以创建临时文件和目录。 它适用于所有受支持的平台。 `TemporaryFile`, `NamedTemporaryFile`, `TemporaryDirectory` 和 `SpooledTemporaryFile` 是提供自动清理功能的高层级接口并可用作 上下文管理器。 `mkstemp()` 和 `mkdtemp()` 是需要执行手动清理的低层级函数。

所有可被使用者呼叫的函式和建構函式都帶有可以設定臨時檔案和臨時目錄的路徑和名稱的引數。此 module 所使用的檔名為一個隨機字元組成的字串，這讓檔案可以更安全地在共享的臨時目錄中被建立。為了維持向後相容性，引數的順序會稍微奇怪，所以為了讓程式更容易被理解，建議使用關鍵字引數。

這個 module 定義了以下可供使用者呼叫的項目：

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

  回傳一個可當作臨時儲存區域的 file-like object。建立該檔案使用了與 `mkstemp()` 相同的安全規則。它將在關閉（包括當物件被垃圾回收 (garbage collect) 時的隱式關閉）後立即銷毀。在 Unix 下，該檔案所在的目錄可能根本不被建立、或者在建立檔案後立即就被刪除，其他平臺不支援此功能；你的程式不應依賴使用此功能建立的臨時檔案名稱，因為它在檔案系統中的名稱有可能是不可見的。

  结果对象可以用作 context manager (参见 範例)。 上下文结束或文件对象销毁后会将临时文件从文件系统中移除。

  mode 參數預設為 `'w+b'`，所以建立的檔案不用關閉就可以讀取或寫入。因為用的是二進位制模式，所以無論存的是什麼資料，它在所有平臺上的行為都一致。buffering、encoding、errors 和 newline 的含義與 `open()` 中的相同。

  參數 dir、prefix 和 suffix 的含義和預設值都與它們在 `mkstemp()` 中的相同。

  在 POSIX 平臺上，回傳物件是真實的檔案物件。在其他平臺上，它是一個 file-like object，它的 `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)

  此函式執行的操作與 `TemporaryFile()` 幾乎相同，不同之處為確保該臨時檔案在檔案系統中具有可見的名稱（在 Unix 上目錄條目不會被 unlink）。檔名可以由回傳 file-like object 的 `name` 屬性取得。在臨時檔案仍開啟時，是否允許用檔名第二次開啟檔案，在各個平臺上是不同的（在 Unix 上可以；在 Windows NT 版本以上不行）。如果 delete 為 true（預設值），則檔案會在關閉後立即被刪除。該函式回傳的物件始終是 file-like object，它的 `file` 屬性是底層的真實檔案物件。file-like object 可以像普通檔案一樣在 `with` 陳述句中使用。

  （只有）在 POSIX 上，一个用 SIGKILL 突然终止的进程无法自动删除它所创建的任何 NamedTemporaryFiles。

  引發一個附帶引數 `fullpath` 的 `tempfile.mkstemp` 稽核事件。

  在 3.8 版的變更: 新增 errors 參數。

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.BytesIO` 或 `io.TextIOWrapper` 对象（这取决于所指定的 mode 是二进制还是文本）或真实的文件对象，这取决于 `rollover()` 是否已被调用。 这个文件型对象可以像普通文件一样在 `with` 语句中使用。

  在 3.3 版的變更: 现在 truncate 方法可接受一个 size 参数。

  在 3.8 版的變更: 新增 errors 參數。

  在 3.11 版的變更: 完整实现 `io.BufferedIOBase` 和 `io.TextIOBase` 抽象基类（取决于二进制或文本 mode 是否已指定）。

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

  这个类会使用与 `mkdtemp()` 相同的规则安全地创建一个临时目录。 结果对象可以被用作 context manager (参见 範例)。 在完成上下文或销毁临时目录对象时，新创建的临时目录及其所有内容会从文件系统中被移除。

  name

    可以从所返回对象的 `name` 属性中提取目录名称。 当返回的对象被用作 context manager 时，这个 `name` 将被作为 `with` 语句中 `as` 子句的目标，如果存在该子句的话。

  cleanup()

    此目录可通过调用 `cleanup()` 方法来显式地清理。 如果 ignore_cleanup_errors 为真值，则在显式或隐式清理（例如在 Windows 上 `PermissionError` 移除打开的文件）期间出现的未处理异常将被忽略，并且剩余的可移除条目会被“尽可能”地删除。 在其他情况下，错误将在任何上下文清理发生时被引发（如 `cleanup()` 调用，退出上下文管理器、对象被作为垃圾回收或解释器关闭等情况）。

  引發一個附帶引數 `fullpath` 的 `tempfile.mkdtemp` 稽核事件。

  在 3.2 版新加入.

  在 3.10 版的變更: 新增 ignore_cleanup_errors 參數。

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

  盡可能以最安全的方式建立一個臨時檔案。假設所在平臺正確實作了 `os.open()` 的 `os.O_EXCL` 旗標，則建立檔案時不會有 race condition（競爭條件）的情況。該檔案只能由建立者讀寫，如果所在平臺用 permission bit（許可權位元）來表示檔案是否可執行，則沒有人有執行權。檔案描述器不會被子行程繼承。

  與 `TemporaryFile()` 不同，`mkstemp()` 使用者用完臨時檔案後需要自行將其刪除。

  如果 suffix 不是 `None` 則檔名將以該後綴結尾，若為 `None` 則沒有後綴。`mkstemp()` 不會在檔名和後綴之間加點 (dot)，如果需要加一個點號，請將其放在 suffix 的開頭。

  如果 prefix 不是 `None` 則檔名將以該字首開頭，若為 `None` 則使用預設前綴。預設前綴是 `gettempprefix()` 或 `gettempprefixb()` 函式的回傳值（自動呼叫合適的函式）。

  如果 dir 不為 `None` 則在指定的目錄建立檔案，若為 `None` 則使用預設目錄。預設目錄是從一個相依於平臺的列表中選擇出來的，但是使用者可以設定 TMPDIR、TEMP 或 TMP 環境變數來設定目錄的位置。因此，不能保證生成的臨時檔案路徑是使用者友善的，比如透過 `os.popen()` 將路徑傳遞給外部命令時仍需要加引號 (quoting)。

  如果 suffix、prefix 和 dir 中的任何一個不是 `None`，就要保證它們資料型別相同。如果它們是位元組串，則回傳名稱的型別就是位元組串而非字串。如果不想遵循預設行為但又想要回傳值是位元組串型別，請傳入 `suffix=b''`。

  如果指定了 text 且為真值，檔案會以文字模式開啟。否則，檔案（預設）以二進位制模式開啟。

  `mkstemp()` 回傳一個 tuple，tuple 中，第一個元素是一個作業系統層級 (OS-level) 控制代碼，指向一個開啟的檔案（如同 `os.open()` 的回傳值），第二元素是該檔案的絕對路徑。

  引發一個附帶引數 `fullpath` 的 `tempfile.mkstemp` 稽核事件。

  在 3.5 版的變更: 現在，suffix、prefix 和 dir 可以以位元組串型別按順序提供，以獲得位元組串型別的回傳值。在之前只允許使用字串。suffix 和 prefix 現在可以接受 `None`，並且預設為 `None` 以使用合適的預設值。

  在 3.6 版的變更: dir 參數現在可接受一個類路徑物件 (path-like object)。

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

  盡可能以最安全的方式建立一個臨時目錄，建立該目錄時不會有 race condition 的情況，該目錄只能由建立者讀取、寫入和搜尋。

  `mkdtemp()` 的使用者用完臨時目錄後需要自行將其刪除。

  引數 prefix、suffix 和 dir 的含義與它們在 `mkstemp()` 中相同。

  `mkdtemp()` returns the absolute pathname of the new directory if dir is `None` or is an absolute path. If dir is a relative path, `mkdtemp()` returns a relative path on Python 3.11 and lower. However, on 3.12 it will return an absolute path in all situations.

  引發一個附帶引數 `fullpath` 的 `tempfile.mkdtemp` 稽核事件。

  在 3.5 版的變更: 現在，suffix、prefix 和 dir 可以以位元組串型別按順序提供，以獲得位元組串型別的回傳值。在之前只允許使用字串。suffix 和 prefix 現在可以接受 `None`，並且預設為 `None` 以使用合適的預設值。

  在 3.6 版的變更: dir 參數現在可接受一個類路徑物件 (path-like object)。

tempfile.gettempdir()

  回傳儲存臨時檔案的目錄名稱。這設定了此 module 所有函式 dir 引數的預設值。

  Python 搜尋標準目錄列表來找到呼叫者可以在其中建立檔案的目錄。這個列表是：

  1. `TMPDIR` 環境變數指向的目錄。

  2. `TEMP` 環境變數指向的目錄。

  3. `TMP` 環境變數指向的目錄。

  4. 與平臺相關的位置：

     - 在 Windows 上，目錄依次為 `C:\TEMP`、`C:\TMP`、`\TEMP` 和 `\TMP`。

     - 在所有其他平臺上，目錄依次為 `/tmp`、`/var/tmp` 和 `/usr/tmp`。

  5. 不得已時，使用當前工作目錄。

  搜尋的結果會被 cache（快取）起來，請見下面 `tempdir` 的描述。

  在 3.10 版的變更: 回傳一個字串。在之前的版本中它會回傳任意 `tempdir` 的值而不考慮它的型別，只要它不為 `None`。

tempfile.gettempdirb()

  與 `gettempdir()` 相同，但回傳值為位元組串型別。

  在 3.5 版新加入.

tempfile.gettempprefix()

  回傳用於建立臨時檔案的檔名前綴，它不包含目錄部分。

tempfile.gettempprefixb()

  與 `gettempprefix()` 相同，但回傳值為位元組串型別。

  在 3.5 版新加入.

此 module 使用一個全域性變數來儲存由 `gettempdir()` 回傳的臨時檔案使用的目錄路徑。它可被直接設定以覆蓋選擇過程，但不建議這樣做。此 module 中的所有函式都接受一個 dir 引數，它可被用於指定目錄。這是個推薦的做法，它不會透過改變全域性 API 行為而對其他不預期此行為的程式造成影響。

tempfile.tempdir

  當被設為 `None` 以外的值時，此變數會為此 module 所定義函式的引數 dir 定義預設值，包括確定其型別為位元組串還是字串。它不可以為 path-like object。

  如果在呼叫除 `gettempprefix()` 外的上述任何函式時 `tempdir` 為 `None` (預設值) 則它會按照 `gettempdir()` 中所描述的演算法來初始化。

  備註

  請注意如果你將 `tempdir` 設為位元組串值，會有一個麻煩的副作用：`mkstemp()` 和 `mkdtemp()` 的全域性預設回傳型別會在沒有提供明顯字串型別的 `prefix`、`suffix` 或 `dir` 時被改為位元組串。請不要編寫預期此行為或依賴於此行為的程式。這個奇怪的行為是為了維持與以往實作版本的相容性。

## 範例

以下是 `tempfile` module 的一些常見用法範例：

    >>> 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 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()` 代替。

  回傳一個在呼叫本方法時不存在檔案的絕對路徑。引數 prefix、suffix 和 dir 與 `mkstemp()` 中所用的類似，除了在於不支援位元組串型別的檔名且不支援 `suffix=None` 和 `prefix=None`。

  警告

  使用此功能可能會在程式中引入安全漏洞。當你開始使用本方法回傳的檔案執行任何操作時，可能有人已經捷足先登了。`mktemp()` 的功能可以很輕鬆地用帶有 `delete=False` 參數的 `NamedTemporaryFile()` 代替：

      >>> 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