Quelle est la meilleure façon de choisir un fichier aléatoire dans un répertoire en Python?
Edit: Voici ce que je fais:
import os
import random
import dircache
dir = 'some/directory'
filename = random.choice(dircache.listdir(dir))
path = os.path.join(dir, filename)
Est-ce particulièrement mauvais ou existe-t-il un moyen particulièrement meilleur?
import os, random
random.choice(os.listdir("C:\\")) #change dir name to whatever
Concernant votre question éditée: d'abord, je suppose que vous connaissez les risques de l'utilisation d'un dircache
, ainsi que le fait qu'il soit déconseillé depuis 2.6, et supprimé en 3. .
Deuxièmement, je ne vois pas où existe une condition de concurrence. Votre objet dircache
est fondamentalement immuable (une fois que la liste des répertoires est mise en cache, elle n'est plus jamais lue), donc aucun mal lors des lectures simultanées à partir de celui-ci.
À part cela, je ne comprends pas pourquoi vous voyez un problème avec cette solution. C'est bon.
Si vous souhaitez inclure des répertoires, la réponse de Yuval A. Autrement:
import os, random
random.choice([x for x in os.listdir("C:\\") if os.path.isfile(os.path.join("C:\\", x))])
Solution indépendante de la langue:
1) Obtenez le nombre total. des fichiers dans le répertoire spécifié.
2) Choisissez un nombre aléatoire de 0 à [total no. de fichiers - 1].
3) Obtenez la liste des noms de fichiers en tant que collection correctement indexée ou autre.
4) Choisissez le nième élément, où n est le nombre aléatoire.
Le problème avec la plupart des solutions proposées est que vous chargez toutes vos entrées en mémoire, ce qui peut devenir un problème pour les entrées/hiérarchies volumineuses. Voici une solution adaptée de The Perl Cookbook par Tom Christiansen et Nat Torkington. Pour obtenir un fichier aléatoire n'importe où sous un répertoire:
#! /usr/bin/env python
import os, random
n=0
random.seed();
for root, dirs, files in os.walk('/tmp/foo'):
for name in files:
n=n+1
if random.uniform(0, n) < 1: rfile=os.path.join(root, name)
print rfile
Généraliser un peu fait un script pratique:
$ cat /tmp/randy.py
#! /usr/bin/env python
import sys, random
random.seed()
n=1
for line in sys.stdin:
if random.uniform(0, n)<1: rline=line
n=n+1
sys.stdout.write(rline)
$ /tmp/randy.py < /usr/share/dict/words
chrysochlore
$ find /tmp/foo -type f | /tmp/randy.py
/tmp/foo/bar
La solution la plus simple consiste à utiliser os.listdir & random.choice méthodes
random_file=random.choice(os.listdir("Folder_Destination"))
Jetons un coup d'oeil étape par étape: -
1} La méthode os.listdir renvoie la liste contenant le nom des entrées (fichiers) dans le chemin spécifié.
2} Cette liste est ensuite passée en paramètre à la méthode random.choice qui renvoie un nom de fichier aléatoire à partir de la liste.
3} Le nom du fichier est stocké dans la variable random_file .
Considérant une application en temps réel
Voici un exemple python qui déplacera des fichiers aléatoires d'un répertoire à un autre
import os, random, shutil
#Prompting user to enter number of files to select randomly along with directory
source=input("Enter the Source Directory : ")
dest=input("Enter the Destination Directory : ")
no_of_files=int(input("Enter The Number of Files To Select : "))
print("%"*25+"{ Details Of Transfer }"+"%"*25)
print("\n\nList of Files Moved to %s :-"%(dest))
#Using for loop to randomly choose multiple files
for i in range(no_of_files):
#Variable random_file stores the name of the random file chosen
random_file=random.choice(os.listdir(source))
print("%d} %s"%(i+1,random_file))
source_file="%s\%s"%(source,random_file)
dest_file=dest
#"shutil.move" function moves file from one directory to another
shutil.move(source_file,dest_file)
print("\n\n"+"$"*33+"[ Files Moved Successfully ]"+"$"*33)
Vous pouvez consulter l'ensemble du projet sur github Random File Picker
Pour plus d'informations sur la méthode os.listdir et random.choice , vous pouvez voir tutorialspoint learn python
os.listdir: - méthode Python listdir ()
random.choice: - méthode Python choice ()
Indépendamment du langage utilisé, vous pouvez lire toutes les références aux fichiers d'un répertoire dans une structure de données comme un tableau (quelque chose comme 'listFiles'), obtenir la longueur du tableau. calculer un nombre aléatoire dans la plage de "0" à "arrayLength-1" et accéder au fichier à un certain indice. Cela devrait fonctionner, pas seulement en python.
Si vous ne savez pas à l'avance quels fichiers sont là, vous devrez obtenir une liste, puis choisissez simplement un index aléatoire dans la liste.
Voici une tentative:
import os
import random
def getRandomFile(path):
"""
Returns a random filename, chosen among the files of the given path.
"""
files = os.listdir(path)
index = random.randrange(0, len(files))
return files[index]
EDIT : La question mentionne maintenant la peur d'une "condition de concurrence", que je ne peux que supposer est le problème typique des fichiers ajoutés/supprimés pendant que vous êtes en train d'essayer de choisir un fichier aléatoire.
Je ne crois pas qu'il existe un moyen de contourner cela, à part garder à l'esprit que toute opération d'E/S est intrinsèquement "dangereuse", c'est-à-dire qu'elle peut échouer. Ainsi, l'algorithme pour ouvrir un fichier choisi au hasard dans un répertoire donné devrait:
open()
le fichier sélectionné et gérer un échec, car le fichier peut ne plus être là