2010-03-30 8 views
10

J'ai un programme Python qui doit créer un fichier temporaire nommé qui sera ouvert et fermé plusieurs fois au cours du programme, et devrait être supprimé quand le programme se termine. Malheureusement, aucune des options tempfile semblent fonctionner:Comment créer un fichier temporaire nommé sur Windows en Python?

  • TemporaryFile n'a pas un nom visible
  • NamedTemporaryFile crée un objet de type fichier. J'ai juste besoin d'un nom de fichier. J'ai essayé de fermer l'objet qu'il renvoie (après avoir défini delete = False) mais j'obtiens des erreurs de flux lorsque j'essaie d'ouvrir le fichier plus tard. N'a pas de nom visible.
  • mkstemp il ne garantit pas le fichier est supprimé lorsque le programme quitte
  • mktemp retourne le nom du fichier, mais ne garantit pas le fichier est supprimé lorsque le programme quitte

J'ai essayé d'utiliser mktemp dans les un gestionnaire de contexte, comme ceci:

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() 

... mais cela me donne un WindowsError(32, 'The process cannot access the file because it is being used by another process'). Le nom de fichier est utilisé par un processus que mon programme engendre, et même si je m'assure que le processus se termine avant de quitter, il semble avoir une condition de course hors de mon contrôle.

Quelle est la meilleure façon de gérer cela?

Je n'ai pas à m'inquiéter de la sécurité ici; Cela fait partie d'un module de test, donc le plus néfaste des gens pourrait faire échouer faussement nos tests unitaires. L'horreur!

+0

Les problèmes de sécurité ne touchent pas le programme en utilisant le fichier temporaire, ils affectent l'ensemble du système le fichier temporaire est créé sur (par exemple un lien symbolique à une importante fichier après qu'il a été créé). –

+0

Etes-vous sûr que tous les objets fichier ouvrant le fichier temporaire sont correctement fermés? – user49117

+0

Le nom de fichier est passé à un processus Windows via Popen(), et quand j'en ai fini, j'appelle .flush() sur les flux .sysin, .sysout et .syserr, puis j'appelle .wait() sur le processus. C'est enveloppé dans un ContextManager, donc je suis sûr que ça s'appelle. Je ne suis pas sûr de ce que je pourrais faire d'autre. –

Répondre

1

Si vous ne vous souciez pas de la sécurité, qu'est-ce qui ne va pas?

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

Vous essayez peut-être de surcharger cela. Si vous voulez vous assurer que ce fichier est toujours supprimé lorsque le programme se termine, vous pouvez envelopper votre exécution main() dans un try/finally. Rester 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 est le même que os.remove, selon la documentation. Si c'est le cas, je devrais obtenir la même exception, n'est-ce pas? –

2

J'ai eu exactement le même problème quand je avais besoin d'enregistrer un fichier téléchargé dans le fichier temporaire ouvert à l'aide du module csv. La chose la plus irritante était que le nom de fichier dans WindowsError pointait vers le fichier temporaire, mais l'enregistrement du contenu du fichier de téléchargement dans le tampon StringIO et l'insertion des données du tampon dans le fichier temporaire ont résolu le problème. Pour mes besoins, cela suffisait car les fichiers téléchargés tiennent toujours en mémoire. Le problème était seulement quand j'ai téléchargé un fichier avec un script via le CGI d'Apache, quand j'ai exécuté le script similaire de la console, je ne pouvais pas reproduire le problème cependant.

4

J'avais besoin de quelque chose de semblable aujourd'hui et j'ai fini par écrire le mien. J'utilise atexit.register() pour enregistrer un rappel de fonction qui supprime le fichier lorsque le programme se termine. Notez que les normes de codage pour cela sont légèrement différentes des normes de codage Python typiques (camelCase plutôt que d'utiliser les contours). Ajuster à volonté, bien sûr.

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 

code de test 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() 
Questions connexes