web-dev-qa-db-fra.com

Meilleure façon de choisir un fichier aléatoire dans 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 existe-t-il un moyen particulièrement meilleur?

28
JasonSmith
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.

59
Yuval Adam

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))])
6
mavnn

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.

4
karim79

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
4
keithpjolley

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


1

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.

1
Mork0075

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:

  • En fait open() le fichier sélectionné et gérer un échec, car le fichier peut ne plus être là
  • Se limiter 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
unwind