Meilleur moyen de générer des noms de fichiers aléatoires en Python


97

En Python, quelle est la bonne ou la meilleure façon de générer du texte aléatoire à ajouter à un fichier (nom) que j'enregistre sur un serveur, juste pour m'assurer qu'il n'écrase pas. Je vous remercie!

Réponses:


109

Python a des fonctionnalités pour générer des noms de fichiers temporaires, voir http://docs.python.org/library/tempfile.html . Par exemple:

In [4]: import tempfile

Chaque appel à tempfile.NamedTemporaryFile()entraîne un fichier temporaire différent, et son nom est accessible avec l' .nameattribut, par exemple:

In [5]: tf = tempfile.NamedTemporaryFile()
In [6]: tf.name
Out[6]: 'c:\\blabla\\locals~1\\temp\\tmptecp3i'

In [7]: tf = tempfile.NamedTemporaryFile()
In [8]: tf.name
Out[8]: 'c:\\blabla\\locals~1\\temp\\tmpr8vvme'

Une fois que vous avez le nom de fichier unique, il peut être utilisé comme n'importe quel fichier ordinaire. Remarque : Par défaut, le fichier sera supprimé lors de sa fermeture. Cependant, si le deleteparamètre est False, le fichier n'est pas automatiquement supprimé.

Jeu de paramètres complet:

tempfile.NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])

il est également possible de spécifier le préfixe du fichier temporaire (comme l'un des différents paramètres pouvant être fournis lors de la création du fichier):

In [9]: tf = tempfile.NamedTemporaryFile(prefix="zz")
In [10]: tf.name
Out[10]: 'c:\\blabla\\locals~1\\temp\\zzrc3pzk'

Des exemples supplémentaires pour travailler avec des fichiers temporaires peuvent être trouvés ici


1
Ces fichiers seront-ils supprimés la prochaine fois que je redémarrerai ma machine?
HelloWorld

15
Le problème avec cette solution est qu'elle génère non seulement un nom de fichier, mais également un fichier déjà ouvert. Si vous avez besoin d'un nom de fichier temporaire pour un nouveau fichier, pas encore existant (par exemple, à utiliser comme sortie d'une commande os), cela ne fonctionnera pas. Dans ce cas, vous pouvez faire quelque chose comme str (uuid.uuid4 ()).
Luca

@Luca Merci pour le commentaire supplémentaire, qui est utile et noté pour référence future. Cependant, OP a clairement indiqué qu'il / elle voulait enregistrer un fichier, donc besoin de l'ouvrir, donc cette solution le prévoit.
Levon

Ça dépend. Peut-être qu'il a besoin du nom pour construire un appel de serveur approprié. Pas certain. En tout cas, votre réponse est certainement le cas le plus courant.
Luca

106

Vous pouvez utiliser le module UUID pour générer une chaîne aléatoire:

import uuid
filename = str(uuid.uuid4())

C'est un choix valable, étant donné qu'un générateur d' UUID est extrêmement peu susceptible de produire un identifiant en double (un nom de fichier, dans ce cas):

Ce n'est qu'après avoir généré 1 milliard d'UUID par seconde pendant les 100 prochaines années, que la probabilité de créer un seul duplicata serait d'environ 50%. La probabilité d'un duplicata serait d'environ 50% si chaque personne sur terre possède 600 millions d'UUID.


16
Ceci est également très utile lorsque vous voulez un nom de fichier unique, mais que vous ne voulez pas qu'il soit créé pour l'instant.
Prof. Falken

14
Ou utilisez uuid.uuid4().hexpour obtenir une chaîne hexadécimale sans tirets ( -).
Rockallite

17

une approche courante consiste à ajouter un horodatage comme préfixe / suffixe au nom de fichier pour avoir une relation temporelle avec le fichier. Si vous avez besoin de plus d'unicité, vous pouvez toujours y ajouter une chaîne aléatoire.

import datetime
basename = "mylogfile"
suffix = datetime.datetime.now().strftime("%y%m%d_%H%M%S")
filename = "_".join([basename, suffix]) # e.g. 'mylogfile_120508_171442'

4
Dans un environnement multi-thread, il y a une condition de concurrence possible impliquée dans la séquence 1. Test if file exists, 2. create file.Si un autre processus interrompt le vôtre entre les étapes 1 et 2 et crée le fichier, lorsque votre code reprend, il écrasera le fichier de l'autre processus.
Li-aung Yip

@ Li-aungYip En outre peut également utiliser 6-8 séquences de caractères aléatoires (dans le cas où 2 fichiers sont générés dans la même seconde).
bobobobo

@bobobobo: Ou vous pouvez utiliser le tempfilemodule, qui gère cela pour vous. :)
Li-aung Yip

Je suggère d'ajouter des microsecondes, c'est...strftime("%y%m%d_%H%M%S%f")
AstraSerg

8

L'OP a demandé de créer des noms de fichiers aléatoires et non des fichiers aléatoires . Les heures et les UUID peuvent entrer en collision. Si vous travaillez sur une seule machine (pas un système de fichiers partagé) et que votre processus / thread ne se piétine pas, utilisez os.getpid () pour obtenir votre propre PID et utilisez-le comme élément d'un nom de fichier unique. D'autres processus n'obtiendraient évidemment pas le même PID. Si vous êtes multithread, obtenez l'ID du thread. Si vous avez d'autres aspects de votre code dans lesquels un seul thread ou processus peut générer plusieurs fichiers temporaires différents, vous devrez peut-être utiliser une autre technique. Un index tournant peut fonctionner (si vous ne les conservez pas si longtemps ou si vous n'utilisez pas autant de fichiers, vous vous soucieriez du rollover). Garder un hachage / index global sur les fichiers "actifs" suffirait dans ce cas.

Désolé pour l'explication de longue date, mais cela dépend de votre utilisation exacte.


8

Si vous n'avez pas besoin du chemin du fichier, mais uniquement de la chaîne aléatoire ayant une longueur prédéfinie, vous pouvez utiliser quelque chose comme ça.

>>> import random
>>> import string

>>> file_name = ''.join(random.choice(string.ascii_lowercase) for i in range(16))
>>> file_name
'ytrvmyhkaxlfaugx'

7

Si vous souhaitez conserver le nom de fichier d'origine en tant que partie du nouveau nom de fichier, des préfixes uniques de longueur uniforme peuvent être générés en utilisant les hachages MD5 de l'heure actuelle:

from hashlib import md5
from time import localtime

def add_prefix(filename):
    prefix = md5(str(localtime()).encode('utf-8')).hexdigest()
    return f"{prefix}_{filename}"

Les appels à add_prefix ('style.css') génèrent une séquence comme:

a38ff35794ae366e442a0606e67035ba_style.css
7a5f8289323b0ebfdbc7c840ad3cb67b_style.css

1
Pour éviter: les objets Unicode doivent être encodés avant le hachage, j'ai changé en md5 (str (localtime ()). Encode ('utf-8')). Hexdigest ()
PhoebeB

1
Notez qu'un hachage de tout type de données (y compris un horodatage) ne garantit pas l'unicité en soi (pas plus qu'une séquence d'octets choisie au hasard).
Peter O.24

1

Ajout de mes deux cents ici:

In [19]: tempfile.mkstemp('.png', 'bingo', '/tmp')[1]
Out[19]: '/tmp/bingoy6s3_k.png'

Selon la documentation python pour tempfile.mkstemp, il crée un fichier temporaire de la manière la plus sécurisée possible. Veuillez noter que le fichier existera après cet appel:

In [20]: os.path.exists(tempfile.mkstemp('.png', 'bingo', '/tmp')[1])
Out[20]: True

1

Personnellement, je préfère que mon texte ne soit pas seulement aléatoire / unique mais aussi beau, c'est pourquoi j'aime la librairie hashids, qui génère un beau texte aléatoire à partir d'entiers. Peut être installé via

pip install hashids

Fragment:

import hashids
hashids = hashids.Hashids(salt="this is my salt", )
print hashids.encode(1, 2, 3)
>>> laHquq

Brève description:

Hashids est une petite bibliothèque open-source qui génère des identifiants courts, uniques et non séquentiels à partir de nombres.


0
>>> import random
>>> import string    
>>> alias = ''.join(random.choice(string.ascii_letters) for _ in range(16))
>>> alias
'WrVkPmjeSOgTmCRG'

Vous pouvez changer 'string.ascii_letters' en n'importe quel format de chaîne comme vous le souhaitez pour générer n'importe quel autre texte, par exemple mobile NO, ID ... entrez la description de l'image ici


0
import uuid
   imageName = '{}{:-%Y%m%d%H%M%S}.jpeg'.format(str(uuid.uuid4().hex), datetime.now())

1
Bien que ce code puisse résoudre la question, inclure une explication sur comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message et entraînerait probablement plus de votes à la hausse. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limites et des hypothèses applicables.
Богдан Опир

-1

Vous pouvez utiliser le package aléatoire:

import random
file = random.random()

file = str (random.random ())
anajem

Cela génère des nombres aléatoires, pas un texte aléatoire.
user1767754
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.