tempfile - Oggetti Temporanei di File System

Scopo: Crea oggetti di file system temporanei

Creare in sicurezza file temporanei con nomi univoci, in modo che nessuno possa identificarli nel tentativo di forzare una applicazione o catturarne i dati è impegnativo. Il modulo tempfile fornisce parecchie funzioni per creare risorse temporanee di file system in sicurezza. TemporaryFile() apre e restituisce un file senza nome, NamedTemporaryFile() apre e restituisce un file con un nome, SpooledTemporaryFile mantiene il suo contenuto in memoria prima di scriverlo su disco e TemporaryDirectory() è un gestore di contesto che elimina la directory quanto il contesto viene chiuso.

File Temporanei

Applicazioni che necessitano di file temporanei per conservare dati, senza condividere quel file con altri programmi, dovrebbero usare la funzione TemporaryFile() per creare i file. Essa crea un file e, nelle piattaforme in cui è possibile, esegue immediatamente un operazione di unlink. Questo rende impossibile a un altro programma il trovare o aprire il file, visto che non esiste nessun riferimento a esso nella tabella del file system. Il file creato da TemporaryFile() viene eliminato automaticamente quando viene chiuso, sia che lo si faccia chiamando close() oppure utilizzando l'API del gestore di contesto con l'istruzione with.

# tempfile_TemporaryFile.py

import os
import tempfile

print('Creazione di un nome di file con PID:')
filename = '/tmp/indovina_il_nome.{}.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('File Temporaraneo:')
with tempfile.TemporaryFile() as temp:
    print('temp:')
    print('  {!r}'.format(temp))
    print('temp.name:')
    print('  {!r}'.format(temp.name))

# Elimina il file automaticamente

Questo esempio illustra la differenza tra il creare un file temporaneo usando una operatività comune per impostarne il nome, e l'usare la funzione TemporaryFile() . Il file restituito da TemporaryFile non ha un nome.

$ python3 tempfile_TemporaryFile.py

Creazione di un nome di file con PID:
temp:
  <_io.BufferedRandom name='/tmp/indovina_il_nome.16226.txt'>
temp.name:
  '/tmp/indovina_il_nome.16226.txt'

File Temporaraneo:
temp:
  <_io.BufferedRandom name=3>
temp.name:
  3

In modalità predefinita, l'handle del file viene creato con modalità 'w+b', in modo che si comporti consistentemente su tutte le piattaforme e il chiamante può scrivere o leggere da esso.

import os
import tempfile

temp = tempfile.TemporaryFile()
try:
    temp.write('Qualche dato')
    temp.seek(0)

    print temp.read()
finally:
    temp.close()

Nella modalità predefinita, l'handle del file viene creato nella modalità 'w+b' in modo da comportarsi in modo consistente su tutte le piattaforme e il chiamante può da esso scrivere e leggere.

# tempfile_TemporaryFile_binary.py

import os
import tempfile

with tempfile.TemporaryFile() as temp:
    temp.write(b'Qualche dato')

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

Dopo la scrittura si deve "riavvolgere" l'handle del file usando seek() per potere leggere di nuovo i dati da esso.

$ python3 tempfile_TemporaryFile_binary.py

b'Qualche dato'

Per aprire il file in formato testo, si passa mode='w+t' quando lo si crea:

# tempfile_TemporaryFile_text.py

import tempfile

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

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

L'handle del file considera i dati come testo:

$ python3 tempfile_TemporaryFile_text.py

primo
secondo

File Nominati

Ci sono situazioni nelle quali avere un file temporaneo con un nome è importante. Se una applicazione sviluppa processi multipli, o anche host, nominare il file diventa il modo più semplice per passarlo tra le parti dell'applicazione. La funzione NamedTemporaryFile() crea un file senza toglierne il collegamento, in modo che esso conservi il suo nome, al quale si accede con l'attributo name.

# tempfile_NamedTemporaryFile.py

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('Esiste dopo la chiusura:', f.exists())

Il file viene rimosso dopo che l'handle viene chiuso.

$ python3 tempfile_NamedTemporaryFile.py

temp:
  <tempfile._TemporaryFileWrapper object at 0x7f642f22aa58>
temp.name:
  '/tmp/tmpdvrok0ji'
Esiste dopo la chiusura: False

File in Memoria

Per file temporanei che contengono una limitata mole di dati, è probabilmente più efficace l'utilizzo di SpooledTemporaryFile in quanto il contenuto del file viene trattenuto in memoria tramite un buffer io.BytesIO oppure io.StringIO fino a che viene raggiunta una dimensione soglia. Quando i dati superano questa soglia, vengono scritti su disco e il buffer viene sostituito da un normale TemporaryFile().

# tempfile_SpooledTemporaryFile.py

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('Questa riga viene ripetuta ad libitum.\n')
        print(temp._rolled, temp._file)

Questo esempio utilizza gli attributi privati di SpooledTemporaryFile per determinare quando il riversamento (rollover) su disco accade. Questo non è normalmente necessario per verificare lo stato a meno che non si stia aggiustando la dimensione del buffer.

$ python3 tempfile_SpooledTemporaryFile.py

temp: <tempfile.SpooledTemporaryFile object at 0x7f7a5f738a20>
False <_io.StringIO object at 0x7f7a5f782708>
False <_io.StringIO object at 0x7f7a5f782708>
True <_io.TextIOWrapper name=3 mode='w+t' encoding='utf-8'>

Per provocare una esplicita scrittura del buffer su disco, si invocano i metodi rollover() oppure fileno().

# tempfile_SpooledTemporaryFile_explicit.py

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('Questa riga viene ripetuta ad libitum.\n')
        print(temp._rolled, temp._file)
    print('scrittura del buffer')
    temp.rollover()
    print(temp._rolled, temp._file)

In questo esempio, visto che la dimensione del buffer è molto di più grande dei dati stessi, non verrebbe creato alcun file su disco se non venisse chiamato rollover().

$ python3 tempfile_SpooledTemporaryFile_explicit.py

temp: <tempfile.SpooledTemporaryFile object at 0x7f624959f780>
False <_io.StringIO object at 0x7f62495e6708>
False <_io.StringIO object at 0x7f62495e6708>
False <_io.StringIO object at 0x7f62495e6708>
scrittura del buffer
True <_io.TextIOWrapper name=3 mode='w+t' encoding='utf-8'>

Directory Temporanee

Se occorrono diversi file temporanei, potrebbe essere molto più conveniente creare una singola directory temporanea con TemporaryDirectory, quindi aprire tutti i file in essa.

# tempfile_TemporaryDirectory.py

import pathlib
import tempfile

with tempfile.TemporaryDirectory() as directory_name:
    the_dir = pathlib.Path(directory_name)
    print(the_dir)
    a_file = the_dir / 'un_file.txt'
    a_file.write_text('Questo file viene eliminato.')

print('La directory eiste dopo?', the_dir.exists())
print('Contenuto dopo:', list(the_dir.glob('*')))

Il gestore di contesto produce il nome della directory, che può poi essere usato all'interno del blocco del contesto per costruire altri nomi di file.

$ python3 tempfile_TemporaryDirectory.py

/tmp/tmpm253msqx
La directory eiste dopo? False
Contenuto dopo: []

Predire i nomi

Sebbene sia meno sicuro rispetto ai file temporanei strettamente anonimi, includere una porzione prevedibile nel nome consente di trovare il file ed esaminarlo per scopi di debug. Tutte le funzioni fin qui descritte ricevono tre parametri per consentire il controllo dei nomi dei file fino a un certo punto. I nomi sono generati usando la formula:

dir + prefix (prefisso) + random (casuale) + suffix (suffisso).

Tutti i valori tranne casuale possono essere passati come argomenti delle funzioni per creare directory e file temporanei.

# tempfile_NamedTemporaryFile_args.py

import tempfile

with tempfile.NamedTemporaryFile(suffix='_suffisso',
                                 prefix='prefisso_',
                                 dir='/tmp') as temp:
    print('temp:')
    print('  ', temp)
    print('temp.name:')
    print('  ', temp.name)

Gli argomenti prefix e suffix sono combinati assieme a una stringa casuale di caratteri per costruire il nome del file, ed l'argomento dir viene ricevuto così com'è e usato come locazione del nuovo file.

$ python3 tempfile_NamedTemporaryFile.py

temp:
  <tempfile._TemporaryFileWrapper object at 0x7f6ba21397b8>
temp.name:
  '/tmp/tmpmc08iq_w'
Esiste dopo la chiusura: False

Locazione dei file temporanei

Se non viene specificata esplicitamente una destinazione attraverso l'argomento dir, il percorso usato per i file temporanei assumerà valori diversi a seconda della piattaforma di esecuzione e delle impostazioni. Il modulo tempfile include due funzioni per interrogare le impostazioni che sono usate in fase di esecuzione.

# tempfile_settings.py

import tempfile

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

gettempdir() restituisce la directory predefinita che conterrà tutti i file temporanei e gettempprefix() ritorna la stringa del prefisso per i nomi del nuovo file e directory.

$ python3 tempfile_settings.py

gettempdir(): /tmp
gettempprefix(): tmp

Il valore restituito da gettempdir() viene impostato in base a un algoritmo che cerca attraverso un elenco di locazioni il primo posto nel quale il processo corrente può creare un file. La lista di ricerca è:

  1. Il valore della variabile di ambiente TMPDIR
  2. Il valore della variabile di ambiente TEMP
  3. Il valore della variabile di ambiente TMP
  4. Una locazione specifica rispetto alla piattaforma. (Windows usa la prima disponibile tra, le directory: C:\temp, C:\tmp, \temp, o \tmp. Altri piattaforme usano /tmp, /var/tmp, o /usr/tmp.
  5. Se nessuna directory viene trovata, si utilizza la directory corrente.
# tempfile_tempdir.py

import tempfile

tempfile.tempdir = '/Ho/cambiato/questo/percorso'
print('gettempdir():', tempfile.gettempdir())

I programmi che devono utilizzare una locazione globale per tutti i file temporanei senza usare alcuna di queste variabili di ambiente, dovrebbero impostare tempfile.tempdir direttamente assegnando il valore alla variabile.

$ python3 tempfile_tempdir.py

gettempdir(): /Ho/cambiato/questo/percorso

Vedere anche:

tempfile
La documentazione della libreria standard per questo modulo.
random
Generatore di numeri pseudocasuali, utilizzato per inserire valori casuali all'interno dei nomi di file temporanei.