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 訊號突然終止的程序無法自動刪除它建立的任何 NamedTemporaryFiles。

引發帶有引數 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 物件(具體取決於是否指定了二進位制或文字 mode),要麼是一個真正的檔案物件,具體取決於是否已呼叫 rollover()。這個類檔案物件可以像普通檔案一樣在 with 語句中使用。

3.3 版本更改: truncate 方法現在接受 size 引數。

在 3.8 版本中變更: 添加了 errors 引數。

3.11 版本更改: 完全實現了 io.BufferedIOBaseio.TextIOBase 抽象基類(取決於是否指定了二進位制或文字 mode)。

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.O_EXCL 標誌用於 os.open(),則在檔案建立過程中不會出現競爭條件。該檔案僅對建立使用者 ID 可讀寫。如果平臺使用許可權位來指示檔案是否可執行,則該檔案對任何人均不可執行。子程序不會繼承該檔案描述符。

TemporaryFile() 不同,mkstemp() 的使用者有責任在使用完臨時檔案後將其刪除。

如果 suffix 不是 None,則檔名將以該字尾結尾,否則將沒有後綴。mkstemp() 不會在檔名和字尾之間新增點;如果需要點,請將其放在 suffix 的開頭。

如果 prefix 不是 None,則檔名將以該字首開頭;否則,將使用預設字首。預設值是 gettempprefix()gettempprefixb() 的返回值(視情況而定)。

如果 dir 不是 None,則檔案將在該目錄中建立;否則,將使用預設目錄。預設目錄是從平臺相關的列表中選擇的,但應用程式的使用者可以透過設定 TMPDIRTEMPTMP 環境變數來控制目錄位置。因此,不能保證生成的檔名會具有任何良好的屬性,例如在透過 os.popen() 傳遞給外部命令時不需要引號。

如果 suffixprefixdir 中的任何一個不是 None,則它們必須是相同的型別。如果它們是位元組,則返回的名稱將是位元組而不是字串。 如果您想強制使用位元組返回值並保持其他預設行為,請傳遞 suffix=b''

如果指定了 text 並且為 true,則該檔案以文字模式開啟。否則(預設),該檔案以二進位制模式開啟。

mkstemp() 返回一個元組,其中包含一個指向已開啟檔案的作業系統級控制代碼(如 os.open() 返回的)以及該檔案的絕對路徑名,順序如此。

引發帶有引數 fullpath審計事件 tempfile.mkstemp

3.5 版本更改: suffixprefixdir 現在可以以位元組形式提供,以便獲得位元組返回值。在此之前,僅允許字串。suffixprefix 現在接受並預設為 None 以便使用適當的預設值。

3.6 版本更改: dir 引數現在接受 path-like object

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

以儘可能安全的方式建立一個臨時目錄。在目錄建立過程中不會出現競爭條件。該目錄僅對建立使用者 ID 可讀、可寫和可搜尋。

mkdtemp() 的使用者有責任在使用完臨時目錄及其內容後將其刪除。

prefixsuffixdir 引數與 mkstemp() 的相同。

mkdtemp() 返回新目錄的絕對路徑名。

使用引數 fullpath 引發 審計事件 tempfile.mkdtemp

3.5 版本更改: suffixprefixdir 現在可以以位元組形式提供,以便獲得位元組返回值。在此之前,僅允許字串。suffixprefix 現在接受並預設為 None 以便使用適當的預設值。

3.6 版本更改: dir 引數現在接受 path-like object

3.12 版本更改: mkdtemp() 現在始終返回絕對路徑,即使 dir 是相對路徑也是如此。

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

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

警告

使用此函式可能會在程式中引入安全漏洞。在您處理它返回的檔名之前,其他人可能已經搶先一步。mktemp() 的用法可以很容易地替換為 NamedTemporaryFile(),並傳遞 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