2012-01-19 24 views
19

Sto scherzando con le ricerche di file in python su un grande disco rigido. Ho cercato su os.walk e glob. Di solito uso os.walk perché lo trovo molto più ordinato e sembra essere più veloce (per le solite directory di dimensioni).Più veloce a os.walk o glob?

Qualcuno ha avuto esperienza con entrambi e potrebbe dire che è più efficiente? Come ho detto, glob sembra essere più lento, ma è possibile utilizzare i caratteri jolly ecc., Come con walk, è necessario filtrare i risultati. Ecco un esempio di ricerca di core dump.

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

Suona come l'ottimizzazione prematura per me. Ho dato un'occhiata al codice sorgente (http://hg.python.org/cpython/file/d01208ba482f/Lib/glob.py e http://hg.python.org/cpython/file/d01208ba482f/Lib/os.py) e vedi che entrambe le funzioni si basano su 'os.listdir' e' os.isdir', quindi il mio istinto mi dice che non guadagnerai molto in un modo o nell'altro. (Tuttavia, come sottolineato in due delle risposte qui sotto, 'os.walk' ricorre su sottodirectory e' glob.iglob' no, quindi non ha senso confrontare). Se si finisce con un problema di prestazioni, profilo un paio di approcci. Altrimenti, scrivi semplicemente il codice. –

risposta

13

ho fatto una ricerca su un piccola cache delle pagine web in 1000 dirs. L'attività consisteva nel contare un numero totale di file nelle directory. L'output è:

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

Come si vede, os.listdir è più veloce di tre.E glog.glob è ancora più veloce di os.walk per questa attività.

La fonte:

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

Se è necessario recurse attraverso le sottodirectory, utilizzare os.walk. In caso contrario, penso che sarebbe più semplice utilizzare glob.iglob o os.listdir.

+1

+1. Soprattutto per indicare una funzione ricorre attraverso le sottodirectory mentre l'altra no. –

+0

@aculich. Grazie per la correzione. –

+3

@Steven, il modello glob '/ path/to/*/core' usa' * 'come carattere jolly. 'glob' sostituirà' * 'solo con una directory. Ancora non * ricorre * attraverso tutte le sottodirectory. – unutbu

1

È possibile utilizzare os.walk e utilizzare ancora la corrispondenza glob-style.

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

sicuro di velocità, ma, ovviamente, dal momento che è os.walk ricorsiva, fanno cose diverse.

10

Non perdere tempo per l'ottimizzazione prima di misurare/profilare. Concentrati su come rendere il tuo codice semplice e facile da mantenere.

Ad esempio, nel codice si precompila RE, che non fornisce alcun incremento di velocità, poiché il modulo ha un valore interno di re._cache di RE precompilati.

  1. Keep it simple
  2. se è lento, quindi il profilo
  3. una volta che si sa esattamente che cosa deve essere ottimizzato fare alcune modifiche e documentare sempre

nota, che un po 'di ottimizzazione fatto diversi anni prima può rendere il codice più lento rispetto al codice "non ottimizzato". Questo vale soprattutto per i moderni linguaggi basati su JIT.

+1

+1 per un buon consiglio su quando ottimizzare. –

+7

-1. OP ha menzionato un "disco grande". Inoltre, il codice è ovviamente già semplice. Inoltre, OP sembra essere in fase di ottimizzazione. È una piaga su SO per scartare le domande relative alle prestazioni con qualcosa come "le ottimizzazioni premature sono la radice di blabla" (che sono in realtà misquotations di Knuth). – kgadek

+4

-1 l'ottimizzazione è importante nel mondo reale (professionale), dove le cose sono spesso su una scala molto ampia. non solo ciecamente diss ottimizzazione senza alcun motivo razionale – Julius

0

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

penso anche con glob si sarebbe ancora dovuto os.walk, a meno che non si sa direttamente quanto in profondità il vostro albero di sottodirectory è.

Btw. nel glob documentation si dice:

"? *, e gli intervalli di caratteri espressi con [] saranno correttamente abbinato Questo viene fatto usando l'os.listdir() e fnmatch.fnmatch() funzioni."

vorrei semplicemente andare 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)