Python: comment créer un nom de fichier unique?

93

J'ai un formulaire Web python avec deux options - Téléchargement de fichier et zone de texte . Je dois prendre les valeurs de chacun et les transmettre à un autre programme de ligne de commande. Je peux facilement transmettre le nom du fichier avec les options de téléchargement de fichier, mais je ne sais pas comment transmettre la valeur de la zone de texte.

Je pense que ce que je dois faire est:

  1. Générer un nom de fichier unique
  2. Créez un fichier temporaire avec ce nom dans le répertoire de travail
  3. Enregistrez les valeurs passées de textarea dans le fichier temporaire
  4. Exécutez le programme en ligne de commande depuis mon module python et transmettez-lui le nom du fichier temporaire

Je ne sais pas comment générer un nom de fichier unique. Quelqu'un peut-il me donner des conseils sur la façon de générer un nom de fichier unique? Tous les algorithmes, suggestions et lignes de code sont appréciés.

Merci pour votre préoccupation

MysticCodes
la source
1
J'ai modifié votre question pour essayer de la rendre plus claire. Faites-moi savoir si j'ai mal interprété quelque chose!
culix

Réponses:

142

Je ne pense pas que votre question soit très claire, mais si vous n'avez besoin que d'un nom de fichier unique ...

import uuid

unique_filename = str(uuid.uuid4())
ÉnigmeCurry
la source
Désolé, je travaille sur la plate-forme Windows, donc je ne sais pas comment gérer le sous
MysticCodes
uuid semble créer une longue chaîne unique. Je ne pense pas qu'il soit préférable d'avoir un nom de fichier avec une longue chaîne et UUID, () dedans.
MysticCodes
6
Je pense que ce uuid.uuid4().hexserait un meilleur choix, voir les détails ici .
Grey Li
4
@ToloPalmer: Il est plus probable que le processeur de votre ordinateur ait une erreur de traitement qui le pousse à charger le mauvais fichier que si un UUID généré entre en collision avec une valeur existante. UUID produit un nom unique dans un modèle de calcul qui comprend que tous les calculs ne sont pas des mathématiques pures.
GManNickG
2
Pardon my ignorance old comment ... En effet n'est pas unique mais très peu susceptible d'entrer en collision, donc bon choix;)
Tolo Palmer
51

Si vous souhaitez créer des fichiers temporaires en Python, il existe un module appelé tempfile dans les bibliothèques standard de Python. Si vous souhaitez lancer d'autres programmes pour opérer sur le fichier, utilisez tempfile.mkstemp () pour créer des fichiers, et os.fdopen () pour accéder aux descripteurs de fichiers que mkstemp () vous donne.

Incidemment, vous dites que vous exécutez des commandes à partir d'un programme Python? Vous devriez certainement utiliser le module de sous - processus .

Vous pouvez donc écrire assez joyeusement du code qui ressemble à:

import subprocess
import tempfile
import os

(fd, filename) = tempfile.mkstemp()
try:
    tfile = os.fdopen(fd, "w")
    tfile.write("Hello, world!\n")
    tfile.close()
    subprocess.Popen(["/bin/cat", filename]).wait()        
finally:
    os.remove(filename)

En exécutant cela, vous devriez constater que la catcommande a parfaitement fonctionné, mais le fichier temporaire a été supprimé dans le finallybloc. Sachez que vous devez supprimer le fichier temporaire que mkstemp () vous renvoie - la bibliothèque n'a aucun moyen de savoir quand vous en avez terminé!

(Edit: j'avais supposé que NamedTemporaryFile faisait exactement ce que vous recherchez, mais cela pourrait ne pas être si pratique - le fichier est supprimé immédiatement lorsque l'objet de fichier temporaire est fermé, et d'autres processus ouvrent le fichier avant de le fermer ne fonctionnera pas sur certaines plates-formes, notamment Windows. Désolé, échoue de ma part.)

Richard Barrell
la source
utiliser NamedTemporaryFile est probablement ce qu'ils veulent (à moins qu'ils ne veulent qu'il reste sur le serveur, et qu'ils puissent ensuite utiliser "tempfile.NamedTemporaryFile (delete = False)")
Terence Honles
Puis-je également rendre ce nom de fichier temporaire unique? afin que je puisse l'enregistrer plus tard lorsque le sous-processus est terminé avec un nom unique
MysticCodes
@Terence Honles: J'avais suggéré tempfile.NamedTemporaryFile () à l'origine, mais vous ne pouvez pas vraiment l'utiliser pour créer des fichiers temporaires auxquels d'autres processus peuvent accéder sous Windows. NamedTemporaryFile (delete = False) est certainement plus propre , cependant. @ user343934: tempfile.mkstemp () est garanti de vous donner un nom unique à chaque fois qu'il est appelé - il génère les noms au hasard et il utilise les fonctionnalités du système d'exploitation (O_EXCL, si vous vous demandez) pour éviter les collisions.
Richard Barrell
wow je ne savais pas que cela ne fonctionnait pas sur Windows ... échouer: (... je suppose que c'est bon à savoir
Terence Honles
@Terence Honles: NamedTemporaryFile () n'échoue pas réellement sous Windows (pour autant que je sache), mais vous ne pouvez pas fermer le fichier sans le supprimer aussi, et (si je comprends bien la sémantique des fichiers sous Windows) aucun autre programme ne peut ouvrir le fichier pendant que vous l'avez ouvert. J'ai peut être tort; la sémantique pour avoir plusieurs processus partageant un fichier sous Windows peut avoir changé depuis ma dernière vérification.
Richard Barrell
31

Le uuidmodule serait un bon choix, je préfère l'utiliser uuid.uuid4().hexcomme nom de fichier aléatoire car il renverra une chaîne hexadécimale sans tirets .

import uuid
filename = uuid.uuid4().hex

Les sorties devraient ressembler à ceci:

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one
Gray Li
la source
Quel est le problème des tirets?
David Lopez
15

Peut-être avez-vous besoin d'un fichier temporaire unique?

import tempfile

f = tempfile.NamedTemporaryFile(mode='w+b', delete=False)

print f.name
f.close()

f est un fichier ouvert. delete=Falsesignifie ne pas supprimer le fichier après la fermeture.

Si vous avez besoin de contrôler le nom du fichier, il existe des arguments optionnels prefix=...et suffix=...qui acceptent des chaînes. Voir https://docs.python.org/3/library/tempfile.html .

Роман Буртник
la source
C'est génial si vous n'avez pas besoin de contrôler le nom du fichier.
hiwaylon
1
Il doit s'agir de tmpfile.NamedTemporaryFile et pas seulement de NamedTemporaryFile.
user1993015
w+best la valeur par défaut mode. L'utilisation de n'importe quelle tempfilefonctionnalité présente l'inconvénient des autorisations d'accès aux fichiers incorrectes: tempfiledocuments à utiliser os.O_TMPFILEcomme masque, mais la création de fichiers normale respecte os.umask().
m8mble
8

Vous pouvez utiliser le module datetime

import datetime
uniq_filename = str(datetime.datetime.now().date()) + '_' + str(datetime.datetime.now().time()).replace(':', '.')

Notez que: J'utilise replacecar les deux points ne sont pas autorisés dans les noms de fichiers dans de nombreux systèmes d'exploitation.

Voilà, cela vous donnera un nom de fichier unique à chaque fois.

Nimish Agrawal
la source
2
Sauf si les noms de fichiers sont créés immédiatement les uns après les autres (par exemple dans une boucle). Ensuite, ils sont les mêmes.
skjerns
1

Je suis tombé sur cette question, et j'ajouterai ma solution pour ceux qui recherchent peut-être quelque chose de similaire. Mon approche consistait simplement à créer un nom de fichier aléatoire à partir de asciicaractères. Ce sera unique avec une bonne probabilité.

from random import sample
from string import digits, ascii_uppercase, ascii_lowercase
from tempfile import gettempdir
from os import path

def rand_fname(suffix, length=8):
    chars = ascii_lowercase + ascii_uppercase + digits

    fname = path.join(gettempdir(), 'tmp-'
                + ''.join(sample(chars, length)) + suffix)

    return fname if not path.exists(fname) \
                else rand_fname(suffix, length)
behzad.nouri
la source
1
La réponse évidente à la question concernait le package uuid. Cependant, mon serveur cible a python 2.4, aucun package uuid et la mise à niveau n'a été autorisée par le propriétaire du serveur en raison d'incompatibilités logicielles héritées, donc cette réponse fonctionne pour moi.
Alberto Gaona
1
J'aime particulièrement cette réponse: peut être facilement adaptée aux spécifications du projet.
swdev
1
1) Il n'y a aucune raison d'utiliser la récursivité ici, en particulier sans limite. 2) Il existe une condition de concurrence entre l'heure de path.exists()retour Falseet l'heure à laquelle un consommateur ouvre réellement le fichier.
Jonathon Reinhart
1

Cela peut être fait en utilisant la fonction unique du module ufp.path .

import ufp.path
ufp.path.unique('./test.ext')

si le chemin actuel existe dans le fichier 'test.ext'. ufp.path.unique function return './test (d1) .ext'.

c2o93y50
la source
6
ufp fait partie de drupal? pas un module standard
endolith
1

Pour créer un chemin de fichier unique s'il existe, utilisez un package aléatoire pour générer un nouveau nom de chaîne pour le fichier. Vous pouvez vous référer au code ci-dessous pour le même.

import os
import random
import string

def getUniquePath(folder, filename):    
    path = os.path.join(folder, filename)
    while os.path.exists(path):
         path = path.split('.')[0] + ''.join(random.choice(string.ascii_lowercase) for i in range(10)) + '.' + path.split('.')[1]
    return path

Vous pouvez maintenant utiliser ce chemin pour créer un fichier en conséquence.

RoboMex
la source
0

Si vous avez besoin d'identifiants uniques courts comme nom de fichier, essayez shortuuid, shortuuid utilise des lettres et des chiffres minuscules et majuscules, et supprime les caractères similaires tels que l, 1, I, O et 0.

>>> import shortuuid
>>> shortuuid.uuid()
'Tw8VgM47kSS5iX2m8NExNa'
>>> len(ui)
22

par rapport à

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Milind Deore
la source