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?

21
demandé sur JasonSmith 2009-03-31 18:58:41

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.

48
répondu Yuval Adam 2009-03-31 15:19:37

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.

4
répondu karim79 2009-03-31 15:04:36

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))])
4
répondu mavnn 2009-03-31 15:10:40

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
4
répondu keithpjolley 2017-01-28 16:10:51

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.

1
répondu Mork0075 2009-03-31 15:01:49

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
1
répondu unwind 2009-03-31 15:17:43

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


0
répondu THE_PHOENIX_777_TDW 2018-10-01 07:22:37