Meilleure façon de choisir un fichier aléatoire à partir d'un répertoire
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 y a-t-il un moyen particulièrement meilleur?
7 réponses
import os, random
random.choice(os.listdir("C:\\")) #change dir name to whatever
En ce qui concerne votre question éditée: d'abord, je suppose que vous connaissez les risques d'utiliser un dircache
, ainsi que le fait qu'il est obsolète depuis 2.6, et supprimé dans 3.0.
Deuxièmement, je ne vois pas où existe une condition de course ici. Votre objet dircache
est fondamentalement immuable (après la mise en cache de la liste des répertoires, il n'est plus jamais lu), donc pas de mal à en lire simultanément.
Autre que cela, je ne comprends pas pourquoi vous voyez un problème avec cette solution. Il est très bien.
Solution agnostique de langue:
1) Obtenir le nombre total. de 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.
Si vous voulez que les répertoires soient inclus, la réponse de Yuval A. Sinon:
import os, random
random.choice([x for x in os.listdir("C:\\") if os.path.isfile(os.path.join("C:\\", x))])
Le problème avec la plupart des solutions données est que vous chargez toutes vos entrées en mémoire, ce qui peut devenir un problème pour les grandes entrées/hiérarchies. 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 rend 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
Indépendamment de la langue utilisée, Vous pouvez lire toutes les références aux fichiers dans un répertoire dans une structure de données comme un tableau (quelque chose comme 'listFiles'), obtenir la longueur du tableau. calculez un nombre aléatoire dans la plage de ' 0 ' à 'arrayLength-1' et accédez au fichier à l'index spécifique. 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 une peur d'une "condition de course", ce que je ne peux que supposer est le problème typique des fichiers ajoutés/supprimés pendant que vous essayez 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 "dangereux", c'est à dire il peut échouer. Ainsi, l'algorithme pour ouvrir un fichier choisi au hasard dans un répertoire donné devrait:
- en fait
open()
le fichier sélectionné, et gérer un échec, puisque le fichier peut ne plus être là - se limite probablement à un nombre défini d'essais, donc il ne meurt pas si le répertoire est vide ou si aucun des fichiers n'est lisible
La solution la plus simple consiste à utiliser os.listdir & au hasard.choix nethods
random_file=random.choice(os.listdir("Folder_Destination"))
Prenons un coup d'oeil étape par étape :-
1} os.listdir méthode retourne la liste contenant le nom de entrées (fichiers) dans le chemin spécifié.
2} Cette liste est ensuite passée en paramètre à random.choix méthode qui renvoie un nom de fichier aléatoire de la liste.
3} le nom du fichier est stocké dans random_file variable.
en Considérant une application en temps réel
voici un exemple de code 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 Aléatoire Sélecteur De Fichiers
Pour plus de référence sur os.listdir & au hasard.choix méthode, vous pouvez vous référer à tutorialspoint apprendre python
Os.listdir: - méthode Python listdir ()
Aléatoire.choix: - méthode Python choice ()