La mejor manera de elegir un archivo aleatorio de un directorio

¿Cuál es la mejor manera de elegir un archivo aleatorio de un directorio en Python?

Edit: Esto es lo que estoy haciendo:

import os import random import dircache dir = 'some/directory' filename = random.choice(dircache.listdir(dir)) path = os.path.join(dir, filename) 

¿Esto es particularmente malo, o hay una manera particularmente mejor?

 import os, random random.choice(os.listdir("C:\\")) #change dir name to whatever 

Con respecto a su pregunta editada: primero, asumo que conoce los riesgos de usar un dircache , así como el hecho de que está en desuso desde la versión 2.6 y que se eliminó en la dircache 3.0 .

En segundo lugar, no veo dónde existe ninguna condición de raza aquí. Su objeto dircache es básicamente inmutable (después de que la lista de directorios se almacena en caché, nunca se vuelve a leer), por lo que no hay daño en las lecturas concurrentes.

Aparte de eso, no entiendo por qué ve algún problema con esta solución. Está bien.

Si quieres directorios incluidos, la respuesta de Yuval A. De otra manera:

 import os, random random.choice([x for x in os.listdir("C:\\") if os.path.isfile(os.path.join("C:\\", x))]) 

Solución agnóstica del lenguaje:

1) Obtener el total no. de archivos en el directorio especificado.

2) Elija un número aleatorio de 0 a [total no. de archivos – 1].

3) Obtenga la lista de nombres de archivos como una colección adecuadamente indexada o similar.

4) Elija el elemento nth, donde n es el número aleatorio.

El problema con la mayoría de las soluciones que se ofrecen es que cargue todas sus entradas en la memoria, lo que puede convertirse en un problema para entradas / jerarquías grandes. Aquí hay una solución adaptada de The Perl Cookbook por Tom Christiansen y Nat Torkington. Para obtener un archivo aleatorio en cualquier lugar debajo de un directorio:

 #! /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 

Generalizar un poco hace un script útil:

 $ 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 

Independientemente del idioma utilizado, puede leer todas las referencias a los archivos de un directorio en una estructura de datos como una matriz (algo así como ‘listFiles’), obtener la longitud de la matriz. Calcule un número aleatorio en el rango de ‘0’ a ‘arrayLength-1’ y acceda al archivo en el índice determinado. Esto debería funcionar, no solo en python.

Si no sabe de antemano qué archivos hay, deberá obtener una lista, luego seleccione un índice aleatorio en la lista.

Aquí hay un bash:

 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] 

EDITAR : La pregunta ahora menciona el temor a una “condición de carrera”, que solo puedo asumir es el problema típico de los archivos que se agregan / eliminan mientras usted está tratando de elegir un archivo aleatorio.

No creo que haya una manera de evitar eso, aparte de tener en cuenta que cualquier operación de E / S es inherentemente “insegura”, es decir, puede fallar. Por lo tanto, el algoritmo para abrir un archivo elegido al azar en un directorio determinado debe:

  • En realidad, open() el archivo seleccionado y maneje una falla, ya que es posible que el archivo ya no esté allí.
  • Probablemente se limite a un número determinado de bashs, por lo que no muere si el directorio está vacío o si ninguno de los archivos es legible

La solución más sencilla es utilizar los métodos os.listdir y random.choice .

 random_file=random.choice(os.listdir("Folder_Destination")) 

Echémosle un vistazo paso a paso: –

1} El método os.listdir devuelve la lista que contiene el nombre de las entradas (archivos) en la ruta especificada.

2} Esta lista se pasa luego como parámetro al método random.choice que devuelve un nombre de archivo aleatorio de la lista.

3} El nombre del archivo se almacena en la variable random_file .


Teniendo en cuenta una aplicación en tiempo real

Aquí hay un ejemplo de código de Python que moverá archivos aleatorios de un directorio a otro

 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) 

Puedes ver todo el proyecto en github Random File Picker


Para obtener referencias adicionales sobre el método os.listdir y random.choice , puede consultar los tutoriales y aprender python

os.listdir: – Método de listdir () de Python

random.choice: – Método de elección de Python ()