Python3標准庫:tempfile臨時文件系統對象


1. tempfile臨時文件系統對象

要想安全的創建名字唯一的臨時文件,以防止被試圖破壞應用或竊取數據的人猜出,這很有難度。tempfile模塊提供了多個函數來安全的創建臨時文件系統資源。TemporaryFile()打開並返回一個未命名的文件,NamedTemporaryFile()打開並返回一個命名文件,SpooledTemporaryFile在將內容寫入磁盤之前先將其保存在內存中,TemporaryDirectory是一個上下文管理器,上下文關閉時會刪除這個目錄。

1.1 臨時文件

如果應用需要臨時文件來存儲數據,而不需要與其他程序共享這些文件,則應當使用TemporaryFile()函數創建文件。這個函數會創建一個文件,而且如果平台支持,它會立即斷開這個新文件的鏈接。這樣一來,其他程序就不可能找到或打開這個文件,因為文件系統表中根本沒有這個文件的引用。對於TemporaryFile()創建的文件,無論通過調用close()還是結合使用上下文管理器API和with語句,關閉文件時都會自動刪除這個文件。

import os
import tempfile

print('Building a filename with PID:')
filename = '/guess_my_name.{}.txt'.format(os.getpid())
with open(filename, 'w+b') as temp:
    print('temp:')
    print('  {!r}'.format(temp))
    print('temp.name:')
    print('  {!r}'.format(temp.name))

# Clean up the temporary file yourself.
os.remove(filename)

print()
print('TemporaryFile:')
with tempfile.TemporaryFile() as temp:
    print('temp:')
    print('  {!r}'.format(temp))
    print('temp.name:')
    print('  {!r}'.format(temp.name))

這個例子展示了采用不同方法創建臨時文件的差別,一種做法是使用一個通用模式來構造臨時文件的文件名,另一種做法是使用TemporaryFile()函數。TemporaryFile()返回的文件沒有文件名。

默認的,文件句柄是使用模式'w+b'創建的,以便它在所有平台上都表現一致,並允許調用者讀寫這個文件。 

import os
import tempfile

with tempfile.TemporaryFile() as temp:
    temp.write(b'Some data')

    temp.seek(0)
    print(temp.read())

寫文件之后,必需使用seek()"回轉"文件句柄以便從文件讀回數據。

要以文本模式打開文件,創建文件時要設置mode為'w+t'。

import tempfile

with tempfile.TemporaryFile(mode='w+t') as f:
    f.writelines(['first\n', 'second\n'])

    f.seek(0)
    for line in f:
        print(line.rstrip())

這個文件句柄將把數據處理為文本。

1.2 命名文件

有些情況下,可能非常需要一個命名的臨時文件。對於跨多個進程甚至主機的應用來說,為文件命名是在應用不同部分之間傳遞文件的最簡單的方法。NamedTemporaryFile()函數會創建一個文件,但不會斷開它的鏈接,所以會保留它的文件名(用name屬性訪問)。 

import os
import pathlib
import tempfile

with tempfile.NamedTemporaryFile() as temp:
    print('temp:')
    print('  {!r}'.format(temp))
    print('temp.name:')
    print('  {!r}'.format(temp.name))

    f = pathlib.Path(temp.name)

print('Exists after close:', f.exists())

句柄關閉后文件將被刪除。

1.3 假脫機文件

如果臨時文件中包含的數據相對較少,則使用SpooledTemporaryFile可能更高效,因為它使用一個io.BytesIO或io.stringIO緩沖區在內存中保存內容,直到數據達到一個閾值時,數據將“滾動”並寫入磁盤,然后用常規的TemporaryFile()替換這個緩沖區。 

import tempfile

with tempfile.SpooledTemporaryFile(max_size=100,
                                   mode='w+t',
                                   encoding='utf-8') as temp:
    print('temp: {!r}'.format(temp))

    for i in range(3):
        temp.write('This line is repeated over and over.\n')
        print(temp._rolled, temp._file)

這個例子使用SpooledTemporaryFile的私有屬性來確定何時滾動到磁盤。除非要調整緩沖區大小,否則很少需要檢查這個狀態。

要顯示的將緩沖區寫至磁盤,可以調用rollover()或fileno()方法。 

import tempfile

with tempfile.SpooledTemporaryFile(max_size=1000,
                                   mode='w+t',
                                   encoding='utf-8') as temp:
    print('temp: {!r}'.format(temp))

    for i in range(3):
        temp.write('This line is repeated over and over.\n')
        print(temp._rolled, temp._file)
    print('rolling over')
    temp.rollover()
    print(temp._rolled, temp._file)

在這個例子中,由於緩沖區非常大,遠遠大於實際的數據量,所以除非調用rollover(),否則不會在磁盤上創建任何文件。

1.4 臨時目錄

需要多個臨時文件時,可能更方便的做法是用TemporaryDirectory創建一個臨時目錄,並打開該目錄中的所有文件。 

import pathlib
import tempfile

with tempfile.TemporaryDirectory() as directory_name:
    the_dir = pathlib.Path(directory_name)
    print(the_dir)
    a_file = the_dir / 'a_file.txt'
    a_file.write_text('This file is deleted.')

print('Directory exists after?', the_dir.exists())
print('Contents after:', list(the_dir.glob('*')))

上下文管理器會生成目錄名,可以在上下文塊中用來建立其他文件名。

1.5 臨時文件位置

如果沒有使用dir參數指定明確的目標位置,則臨時文件使用的路徑會根據當前平台和設置而變化。tempfile模塊包括兩個函數來查詢運行時使用的設置。

import tempfile

print('gettempdir():', tempfile.gettempdir())
print('gettempprefix():', tempfile.gettempprefix())

gettempdir()返回包含所有臨時文件的默認目錄,gettempprefix()返回新文件和目錄名和字符串前綴。

gettempdir()返回的值根據一個簡單算法來設置,它會查找一個位置列表,尋找第一個允許當前進程創建文件的位置。

import tempfile

tempfile.tempdir = '/I/changed/this/path'
print('gettempdir():', tempfile.gettempdir())

如果程序需要對所有臨時文件使用一個全局位置,但不使用以上任何環境變量,則應當直接設置tempfile.tempdir,為該變量賦一個值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM