python3從零學習-5.4.6、生成臨時文件和目錄tempfile

源代碼: Lib/tempfile.py

       該模塊用於創建臨時文件和目錄,它可以跨平臺使用。TemporaryFileNamedTemporaryFileTemporaryDirectory 和 SpooledTemporaryFile 是帶有自動清理功能的高級接口,可用作上下文管理器。mkstemp() 和 mkdtemp() 是低級函數,使用完畢需手動清理。
所有由用戶調用的函數和構造函數都帶有參數,這些參數可以設置臨時文件和臨時目錄的路徑和名稱。該模塊生成的文件名包括一串隨機字符,在公共的臨時目錄中,這些字符可以讓創建文件更加安全。爲了保持向後兼容性,參數的順序有些奇怪。所以爲了代碼清晰,建議使用關鍵字參數。
這個模塊定義了以下內容供用戶調用:
  • tempfile.TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None)

       返回一個 file-like object 作爲臨時存儲區域。創建該文件使用了與 mkstemp() 相同的安全規則。它將在關閉後立即銷燬(包括垃圾回收機制關閉該對象時)。在 Unix 下,該文件在目錄中的條目根本不創建,或者創建文件後立即就被刪除了,其他平臺不支持此功能。您的代碼不應依賴使用此功能創建的臨時文件名稱,因爲它在文件系統中的名稱可能是可見的,也可能是不可見的。
生成的對象可以用作上下文管理器(參見 例子)。完成文件對象的上下文或銷燬後,臨時文件將從文件系統中刪除。
mode 參數默認值爲 'w+b' 因此創建的文件可以讀取或寫入而不用關閉。 因爲是使用二進制模式,所以它在所有平臺上的行爲都保持一致而不用關心所存儲的是什麼數據。 bufferingencoding 和 newline 的解讀方式與 open() 相同。
參數 dirprefix 和 suffix 的含義和默認值都與它們在 mkstemp() 中的相同。
在 POSIX 平臺上,它返回的對象是真實的文件對象。在其他平臺上,它是一個文件類對象 (file-like object),它的 file 屬性是底層的真實文件對象。
       如果可用,則使用 os.O_TMPFILE 標誌(僅限於 Linux,需要 3.11 及更高版本的內核)。
       在 3.5 版更改: 如果可用,現在用的是 os.O_TMPFILE 標誌。
  • tempfile.NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True)

       此函數執行的操作與 TemporaryFile() 完全相同,但確保了該臨時文件在文件系統中具有可見的名稱(在 Unix 上表現爲目錄條目不取消鏈接)。從返回的文件類對象的 name 屬性中可以檢索到文件名。在臨時文件仍打開時,是否允許用文件名第二次打開文件,在各個平臺上是不同的(在 Unix 上可以,但在 Windows NT 或更高版本上不行)。如果 delete 爲 true(默認值),則文件會在關閉後立即被刪除。該函數返回的對象始終是文件類對象 (file-like object),它的 file 屬性是底層的真實文件對象。文件類對象可以像普通文件一樣在 with 語句中使用。
 
  • tempfile.SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None)

      此函數執行的操作與 TemporaryFile() 完全相同,但會將數據緩存在內存中,直到文件大小超過 max_size,或調用文件的 fileno() 方法爲止,此時數據會被寫入磁盤,並且寫入操作與 TemporaryFile() 相同。
此函數生成的文件對象有一個額外的方法——rollover(),可以忽略文件大小,讓文件立即寫入磁盤。
The returned object is a file-like object whose _file attribute is either an io.BytesIO or io.StringIO object (depending on whether binary or text mode was specified) or a true file object, depending on whether rollover() has been called. This file-like object can be used in a with statement, just like a normal file.
在 3.3 版更改: 現在,文件的 truncate 方法可接受一個 size 參數。
 
  • tempfile.TemporaryDirectory(suffix=None, prefix=None, dir=None)

       此函數會安全地創建一個臨時目錄,且使用與 mkdtemp() 相同的規則。此函數返回的對象可用作上下文管理器。完成上下文或銷燬臨時目錄對象後,新創建的臨時目錄及其所有內容將從文件系統中刪除。
The directory name can be retrieved from the name attribute of the returned object. When the returned object is used as a context manager, the name will be assigned to the target of the as clause in the with statement, if there is one.
可以調用 cleanup() 方法來手動清理目錄。
3.2 新版功能.
 
  • tempfile.mkstemp(suffix=None, prefix=None, dir=None, text=False)

       以最安全的方式創建一個臨時文件。假設所在平臺正確實現了 os.open() 的 os.O_EXCL 標誌,則創建文件時不會有競爭的情況。該文件只能由創建者讀寫,如果所在平臺用權限位來標記文件是否可執行,那麼沒有人有執行權。文件描述符不會過繼給子進程。
與 TemporaryFile() 不同,mkstemp() 用戶用完臨時文件後需要自行將其刪除。
如果 suffix 不是 None 則文件名將以該後綴結尾,是 None 則沒有後綴。mkstemp() 不會在文件名和後綴之間加點,如果需要加一個點號,請將其放在 suffix 的開頭
如果 prefix 不是 None,則文件名將以該前綴開頭,是 None 則使用默認前綴。默認前綴是 gettempprefix() 或 gettempprefixb() 函數的返回值(自動調用合適的函數)。
如果 dir 不爲 None,則在指定的目錄創建文件,是 None 則使用默認目錄。默認目錄是從一個列表中選擇出來的,這個列表不同平臺不一樣,但是用戶可以設置 TMPDIRTEMP 或 TMP 環境變量來設置目錄的位置。因此,不能保證生成的臨時文件路徑很規範,比如,通過 os.popen() 將路徑傳遞給外部命令時仍需要加引號。
如果 suffixprefix 和 dir 中的任何一個不是 None,就要保證它們是同一數據類型。如果它們是 bytes,則返回的名稱的類型就是 bytes 而不是 str。如果確實要用默認參數,但又想要返回值是 bytes 類型,請傳入 suffix=b''
如果指定了 text 參數,它表示的是以二進制模式(默認)還是文本模式打開文件。在某些平臺上,兩種模式沒有區別。
mkstemp() 返回一個元組,元組中第一個元素是句柄,它是一個系統級句柄,指向一個打開的文件(等同於 os.open() 的返回值),第二元素是該文件的絕對路徑。
在 3.5 版更改: 現在,suffixprefix 和 dir 可以以 bytes 類型按順序提供,以獲得 bytes 類型的返回值。之前只允許使用 str。suffix 和 prefix 現在可以接受 None,並且默認爲 None 以使用合適的默認值。
 
  • tempfile.mkdtemp(suffix=None, prefix=None, dir=None)

      以最安全的方式創建一個臨時目錄,創建該目錄時不會有競爭的情況。該目錄只能由創建者讀取、寫入和搜索。
mkdtemp() 用戶用完臨時目錄後需要自行將其刪除。
prefixsuffix 和 dir 的含義與它們在 mkstemp() 中的相同。
mkdtemp() 返回新目錄的絕對路徑名。
在 3.5 版更改: 現在,suffixprefix 和 dir 可以以 bytes 類型按順序提供,以獲得 bytes 類型的返回值。之前只允許使用 str。suffix 和 prefix 現在可以接受 None,並且默認爲 None 以使用合適的默認值。
  • tempfile.gettempdir()

返回放置臨時文件的目錄的名稱。這個方法的返回值就是本模塊所有函數的 dir 參數的默認值。
Python 搜索標準目錄列表,以找到調用者可以在其中創建文件的目錄。這個列表是:
  1. TMPDIR 環境變量指向的目錄。
  2. TEMP 環境變量指向的目錄。
  3. TMP 環境變量指向的目錄。
  4. 與平臺相關的位置:
  5. 在 Windows 上,依次爲 C:\TEMPC:\TMP\TEMP 和 \TMP
  6. 在所有其他平臺上,依次爲 /tmp/var/tmp 和 /usr/tmp
  7. 不得已時,使用當前工作目錄。
搜索的結果會緩存起來,參見下面 tempdir 的描述。
  • tempfile.gettempdirb()

與 gettempdir() 相同,但返回值爲字節類型。
3.5 新版功能.
  • tempfile.gettempprefix()

返回用於創建臨時文件的文件名前綴,它不包含目錄部分。
  • tempfile.gettempprefixb()

與 gettempprefix() 相同,但返回值爲字節類型。
3.5 新版功能.
本模塊使用一個全局變量來存儲由 gettempdir() 返回的臨時文件目錄路徑。可以直接給它賦值,這樣可以覆蓋自動選擇的路徑,但是不建議這樣做。本模塊中的所有函數都帶有一個 dir 參數,該參數可用於指定目錄,這是推薦的方法。
  • tempfile.tempdir

當設置爲 None 以外的其他值時,此變量將決定本模塊所有函數的 dir 參數的默認值。
如果在調用除 gettempprefix() 外的上述任何函數時 tempdir 爲 None (默認值) 則它會按照 gettempdir() 中所描述的算法來初始化。

例子

以下是 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 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() 來代替。
返回一個絕對路徑,這個路徑指向的文件在調用本方法時不存在。prefixsuffix 和 dir 參數與 mkstemp() 中的同名參數類似,不同之處在於不支持字節類型的文件名,不支持 suffix=None 和 prefix=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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章