tempfile - Creare risorse temporanee nel filesystem

Scopo Creare risorse temporanee nel filesystem
Versione Python Dalla 1.4 con importanti revisioni di sicurezza nella 2.3

Molti programmi devono creare dei file per scrivere dati intermedi. Creare in sicurezza questi file con nomi univoci, in modo che nessuno possa identificarli nel tentativo di forzare l'applicazione è impegnativo. Il modulo tempfile fornisce parecchie funzioni per creare risorse nel filesystem in sicurezza. TemporaryFile() apre e restituisce un file non-nominato, NamedTemporaryFile() apre e restituisce un file con un nome, mentre mkdtemp() crea una directory temporanea e ne restituisce il nome.

TemporaryFile

Se un'applicazione necessita di un file temporaneo per salvare dei dati, ma non deve dividere quel file con altri programmi, la scelta migliore è quella di creare il file con la funzione TemporaryFile(). Essa crea un file e, nelle piattaforme in cui è possibile, esegue immediatamente un unlink. Questo rende impossibile ad un altro programma di trovare od aprire il file, visto che non esiste nessun riferimento ad esso nella tabella del filesystem. Il file creato da TemporaryFile() viene eliminato automaticamente quando viene chiuso.

import os
import tempfile

print 'Creazione di un nome di file:'
filename = '/tmp/indovina_il_nome.%s.txt' % os.getpid()
temp = open(filename, 'w+b')
try:
    print 'temp:', temp
    print 'temp.name:', temp.name
finally:
    temp.close()
    # Elimina espressamente il file temporaneo
    os.remove(filename)

print
print 'TemporaryFile:'
temp = tempfile.TemporaryFile()
try:
    print 'temp:', temp
    print 'temp.name:', temp.name
finally:
    # Elimina il file automaticamente
    temp.close()

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

$ python tempfile_TemporaryFile.py
Creazione di un nome di file:
temp: 
temp.name: /tmp/indovina_il_nome.19029.txt

TemporaryFile:
temp: ', mode 'w+b' at 0x94488e0>
temp.name: 

In modalità predefinita, l'handle del file viene creato con modalità 'w+b', in modo che si comporti consistentemente su tutte le piattaforme ed un programma possa 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()

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

$ python tempfile_TemporaryFile_binary.py
Qualche dato

Se si vuole che il file lavori in formato testo, si passa mode='w+t' quando lo si crea:

import tempfile

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

    for line in f:
        print line.rstrip()
finally:
    f.close()

L'handle del file considera i dati come testo:

$ python tempfile_TemporaryFile_text.py
primo
secondo

NamedTemporaryFile

Ci sono situazioni, comunque, dove avere un file temporaneo con un nome è importante. Se una applicazione sviluppa processi multipli, od anche host, nominare il file diventa il modo più semplice per passarlo tra le parti dell'applicazione. La funzione NamedTemporaryFile() crea un file con un nome, al quale si accede con l'attributo name.

import os
import tempfile

temp = tempfile.NamedTemporaryFile()
try:
    print 'temp:', temp
    print 'temp.name:', temp.name
finally:
    # Elimina il file automaticamente
    temp.close()
print 'Esiste dopo la chiusura:', os.path.exists(temp.name)

Anche se il file ha un nome viene comunque rimosso non appena l'handle viene chiuso.

$ python tempfile_NamedTemporaryFile.py
temp: ', mode 'w+b' at 0x9756890>
temp.name: /tmp/tmpLQ53Av
Esiste dopo la chiusura: False

mkdtemp

Se occorrono diversi file temporanei, potrebbe essere molto più conveniente creare una singola direcotry temporanea, qundi aprire tutti i file in essa. Per creare una directory temporanea si usa mkdtemp().

import os
import tempfile

directory_name = tempfile.mkdtemp()
print directory_name
# Lo script elimina la directory
os.removedirs(directory_name)

Visto che la directory non è "aperta" di per sè, occorre occuparsi della rimozione quando non serve più.

$ python tempfile_mkdtemp.py
/tmp/tmpzi5Mcm

Predire i nomi

Per scopi di debug, potrebbe essere utile includere qualche indicazione circa l'origine dei file temporanei. Sebbene ovviamente sia meno sicuro rispetto ai file temporanei strettamente anonimi, includere una porzione prevedibile nel nome consente di trovare il file da esaminare mentre il programma lo sta usando. Tutte le funzioni fin qui descritte ricevono tre parametri per consentire il controllo dei nomi dei file fino ad un certo punto. I nomi sono generati usando la formula:

dir + prefix + random + suffix

dove tutti i valori tranne 'random' possono essere passati come parametro a TemporaryFile(), NamedTemporaryFIle() e mkdtemp(). Ad esempio:

import tempfile

temp = tempfile.NamedTemporaryFile(suffix='_suffisso',
                                   prefix='prefisso_',
                                   dir='/tmp',
                                   )
try:
    print 'temp:', temp
    print 'temp.name:', temp.name
finally:
    temp.close()

I parametri prefix e suffix sono combinati assieme ad una stringa casuale di caratteri per costruire il nome del file, ed il parametro dir viene ricevuto così com'è ed usato come locazione del nuovo file.

$ python tempfile_NamedTemporaryFile_args.py
temp: ', mode 'w+b' at 0x9ed2890>
temp.name: /tmp/prefisso_35K6h5_suffisso

Locazione dei file temporanei

Se non viene specificata esplicitamente una destinazione attraverso il parametro 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 fuzioni per interrogare le impostazioni che sono usate in fase di esecuzione.

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.

$ python tempfile_settings.py
gettempdir(): /tmp
gettempprefix(): tmp

Il valore restituito da gettempdir() viene impostato in base ad un algoritmo che cerca attraverso un elenco di locazioni il primo posto nel quale il processo corrente può creare un file. Dalla documentazione della libreria:

Python cerca in una lista standard di directory ed imposta tempdir come la prima nella quale l'utente chiamante può creare il file. La lista comprende:

  • La directory abbinata alla variabile di ambiente TMPDIR
  • La directory abbinata alla variabile di ambiente TEMP
  • La directory abbinata alla variabile di ambiente TMP
  • Una locazione specifica rispetto alla piattaforma
  • Su RiscOS, la directory abbinata alla variabile di ambiente Wimp.
  • Su Windows, le directory:C:TEMP, C:TMP, TEMP, and TMP, in questo ordine.
  • Su tutte le altre piattaforme, le directory /tmp, /var/tmp, and /usr/tmp, in quest'ordine
  • Come ultima risorsa, la directory corrente.

Se il programma deve usare un locazione globale per tutti i file temporanei che deve essere creata esplicitamente ma non lo si vuole fare attraverso una di queste variabili di ambiente, si può impostare tempfile.tempdir direttamente.

import tempfile

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

Vedere anche:

tempfile
La documentazione della libreria standard per questo modulo.