2010-03-30 2 views
10

Ho un programma Python che deve creare un file temporaneo con nome che verrà aperto e chiuso un paio di volte nel corso del programma, e dovrebbe essere cancellato quando il programma termina. Purtroppo, nessuna delle opzioni in tempfile sembra funzionare:Come posso creare un file temporaneo con nome su Windows in Python?

  • TemporaryFile non hai un nome visibile
  • NamedTemporaryFile crea un oggetto simile a file. Ho solo bisogno di un nome di file. Ho provato a chiudere l'oggetto restituito (dopo aver impostato delete = False) ma ottengo errori di flusso quando tento di aprire il file in un secondo momento.
  • non ha un nome visibile
  • mkstemp restituisce sia l'oggetto file aperto che il nome; non garantisce il file viene eliminato quando il programma esce
  • mktemp restituisce il nome del file, ma non garantisce il file viene eliminato quando il programma esce

Ho provato con mktemp all'interno un gestore di contesto, in questo modo:

def get_temp_file(suffix): 
    class TempFile(object): 
     def __init__(self): 
      self.name = tempfile.mktemp(suffix = '.test') 

     def __enter__(self): 
      return self 

     def __exit__(self, ex_type, ex_value, ex_tb): 
      if os.path.exists(self.name): 
       try: 
        os.remove(self.name) 
       except: 
        print sys.exc_info() 

    return TempFile() 

... ma che mi dà un WindowsError(32, 'The process cannot access the file because it is being used by another process'). Il nome del file è usato da un processo che il mio programma genera, e anche se mi assicuro che il processo finisca prima di uscire, sembra che abbia una condizione di competizione fuori dal mio controllo.

Qual è il modo migliore per affrontare questo?

Non ho bisogno di preoccuparmi della sicurezza qui; questo fa parte di un modulo di test, quindi la maggior parte delle persone malvagie potrebbe fare in modo che i nostri test unitari falliscano spuriemente. L'orrore!

+0

Le questioni di sicurezza non incidono il programma utilizzando il file temporaneo, interessano l'intero sistema il file temporaneo viene creato (ad esempio, un collegamento simbolico a un importante file dopo che è stato creato). –

+0

Sei sicuro che tutti gli oggetti file che aprono il file temporaneo vengono chiusi correttamente? – user49117

+0

Il nome file viene passato a un processo di Windows tramite Popen(), e quando ho finito con esso, chiamo .flush() sui flussi .sysin, .sysout e .syserr e poi chiamo .wait() sul processi. È racchiuso in un ContextManager, quindi sono sicuro che si chiami. Non sono sicuro di cos'altro potrei fare. –

risposta

1

Se non ti interessa la sicurezza, cosa c'è di sbagliato in questo?

tmpfile_name = tempfile.mktemp() 
# do stuff 
os.unlink(tmpfile_name) 

Si potrebbe provare a eseguire l'over-engineer. Se si desidera assicurarsi che questo file venga sempre rimosso alla chiusura del programma, è possibile eseguire l'esecuzione main() in un try/finally. Keep it simple!

if __name__ == '__main__': 
    try: 
     tmpfile_name = tempfile.mktemp() 
     main() 
    except Whatever: 
     # handle uncaught exception from main() 
    finally: 
     # remove temp file before exiting 
     os.unlink(tmpfile_name) 
+2

os.unlink è lo stesso di os.remove, secondo la documentazione. Se è così, dovrei ottenere la stessa eccezione, giusto? –

2

ho avuto esattamente lo stesso problema quando ho avuto bisogno di salvare un file caricato il file temporaneo aperto utilizzando il modulo csv. La cosa più irritante era che il nome del file in WindowsError puntava al file temporaneo, ma salvando il contenuto del file in upload nel buffer StringIO e spingendo i dati del buffer nel file temporaneo il problema era risolto. Per i miei bisogni è stato sufficiente poiché i file caricati sono sempre in memoria.

Il problema era solo quando ho caricato un file con uno script tramite CGI di Apache, quando eseguivo lo script simile da console non riuscivo a riprodurre il problema.

4

Avevo bisogno di qualcosa di simile oggi e ho finito per scrivere il mio. Sto usando atexit.register() per registrare una funzione callback che rimuove il file quando il programma viene chiuso.

Si noti che gli standard di codifica per questo sono leggermente diversi dai tipici standard di codifica Python (camelCase piuttosto che using_underscores). Regolare a piacimento, ovviamente.

def temporaryFilename(prefix=None, suffix='tmp', dir=None, text=False, removeOnExit=True): 
    """Returns a temporary filename that, like mkstemp(3), will be secure in 
    its creation. The file will be closed immediately after it's created, so 
    you are expected to open it afterwards to do what you wish. The file 
    will be removed on exit unless you pass removeOnExit=False. (You'd think 
    that amongst the myriad of methods in the tempfile module, there'd be 
    something like this, right? Nope.)""" 

    if prefix is None: 
     prefix = "%s_%d_" % (os.path.basename(sys.argv[0]), os.getpid()) 

    (fileHandle, path) = tempfile.mkstemp(prefix=prefix, suffix=suffix, dir=dir, text=text) 
    os.close(fileHandle) 

    def removeFile(path): 
     os.remove(path) 
     logging.debug('temporaryFilename: rm -f %s' % path) 

    if removeOnExit: 
     atexit.register(removeFile, path) 

    return path 
codice di prova

Super-base:

path = temporaryFilename(suffix='.log') 
print path 
writeFileObject = open(path, 'w') 
print >> writeFileObject, 'yay!' 
writeFileObject.close() 

readFileObject = open(path, 'r') 
print readFileObject.readlines() 
readFileObject.close()