2012-01-19 25 views
19

Estoy jugando con las búsquedas de archivos en python en un disco duro grande. He estado mirando os.walk y glob. Usualmente uso os.walk ya que me parece mucho más ordenado y parece ser más rápido (para los directorios de tamaño habitual).Más rápido que os.walk o glob?

¿Alguien ha tenido alguna experiencia con ambos y podría decir cuál es más eficiente? Como digo, glob parece ser más lento, pero puedes usar comodines, etc., como en el caso de caminar, tienes que filtrar los resultados. Aquí hay un ejemplo de búsqueda de volcados de memoria.

core = re.compile(r"core\.\d*") 
for root, dirs, files in os.walk("/path/to/dir/") 
    for file in files: 
     if core.search(file): 
      path = os.path.join(root,file) 
      print "Deleting: " + path 
      os.remove(path) 

O

for file in iglob("/path/to/dir/core.*") 
    print "Deleting: " + file 
    os.remove(file) 
+3

Suena como la optimización prematura a mí. Eché un vistazo a la fuente (http://hg.python.org/cpython/file/d01208ba482f/Lib/glob.py y http://hg.python.org/cpython/file/d01208ba482f/Lib/os.py) y ver que ambas funciones se basan en 'os.listdir' y' os.isdir', por lo que mi instinto me dice que no ganarás mucho en un sentido u otro. (Sin embargo, como se señala en dos de las respuestas a continuación, el 'os.walk' recurre sobre los subdirectorios y' glob.iglob' no, por lo que no tiene sentido comparar). Si terminas con un problema de rendimiento, perfila un par de enfoques. De lo contrario, solo escriba un código claro. –

Respuesta

13

me hizo una investigación sobre una pequeña caché de páginas web en 1000 directorios. La tarea era contar una cantidad total de archivos en directorios. La salida es:

os.listdir: 0.7268s, 1326786 files found 
os.walk: 3.6592s, 1326787 files found 
glob.glob: 2.0133s, 1326786 files found 

Como se ve, os.listdir es más rápida de tres.Y glog.glob es aún más rápido que os.walk para esta tarea.

La fuente:

import os, time, glob 

n, t = 0, time.time() 
for i in range(1000): 
    n += len(os.listdir("./%d" % i)) 
t = time.time() - t 
print "os.listdir: %.4fs, %d files found" % (t, n) 

n, t = 0, time.time() 
for root, dirs, files in os.walk("./"): 
    for file in files: 
     n += 1 
t = time.time() - t 
print "os.walk: %.4fs, %d files found" % (t, n) 

n, t = 0, time.time() 
for i in range(1000): 
    n += len(glob.glob("./%d/*" % i)) 
t = time.time() - t 
print "glob.glob: %.4fs, %d files found" % (t, n) 
12

Si necesita recursivo a través de subdirectorios, os.walk. De lo contrario, creo que sería más fácil usar glob.iglob o os.listdir.

+1

+1. Especialmente para señalar una función recurre a través de subdirectorios mientras que la otra no. –

+0

@aculich. Gracias por la corrección. –

+3

@Steven, el patrón glob '/ path/to/*/core' usa' * 'como un comodín. 'glob' solo reemplazará' * 'con un directorio. Todavía no * recurse * a través de todos los subdirectorios. – unutbu

1

Puede usar os.walk y seguir usando la coincidencia de estilo glob.

for root, dirs, files in os.walk(DIRECTORY): 
    for file in files: 
     if glob.fnmatch.fnmatch(file, PATTERN): 
      print file 
No

seguro acerca de la velocidad, pero obviamente ya os.walk es recursivo, que hacen cosas diferentes.

10

No pierda su tiempo para la optimización antes de medir/perfilar. Concéntrese en hacer que su código sea simple y fácil de mantener.

Por ejemplo, en su código precompila RE, lo que no le da ningún impulso de velocidad, porque el módulo tiene re._cache interno de RE precompilados.

  1. Debe ser sencillo
  2. si es lenta, entonces perfil
  3. una vez que sabe exactamente lo que necesita ser optimizado hacer algunos ajustes y siempre documentarla

Tenga en cuenta, que algunos optimización hecho varias años antes puede hacer que el código se ejecute más lento en comparación con el código "no optimizado". Esto aplica especialmente para los lenguajes modernos basados ​​en JIT.

+1

+1 para obtener buenos consejos sobre cuándo optimizar. –

+7

-1. OP mencionó un "disco grande". Además, el código es obviamente simple ya. Además, OP parece estar en la etapa de optimización. Es una peste en SO descartar preguntas relacionadas con el rendimiento con algo así como "optimizaciones prematuras son raíz de blabla" (que en realidad son citas erróneas de Knuth). – kgadek

+4

-1 La optimización es importante en el mundo real (profesional), donde las cosas a menudo son a gran escala. no solo diste ciegamente la optimización sin ninguna razón racional – Julius

0

*, ?, and character ranges expressed with [] will be correctly matched. This is done by using the os.listdir() and fnmatch.fnmatch() functions

creo que incluso con el pegote que todavía tendría que os.walk, a menos que conozca directamente la profundidad de su árbol de subdirectorio es.

Btw. en el glob documentation que dice:

"? *, y rangos de caracteres expresados ​​con [] estarán correctamente emparejado Esto se hace mediante el uso de la os.listdir() y fnmatch.fnmatch() funciones."

yo simplemente ir con un

for path, subdirs, files in os.walk(path): 
     for name in fnmatch.filter(files, search_str): 
      shutil.copy(os.path.join(path,name), dest)