2012-01-19 14 views
19

Zajmuję się wyszukiwaniem plików w Pythonie na dużym dysku twardym. Patrzyłem na os.walk i glob. Zwykle używam os.walk, ponieważ uważam, że jest dużo bardziej schludny i wydaje się szybszy (dla zwykłych katalogów rozmiarów).Szybciej do os.walk lub glob?

Czy ktoś ma z nimi doświadczenie i może powiedzieć, który jest bardziej wydajny? Jak już mówiłem, glob wydaje się wolniejszy, ale możesz używać symboli wieloznacznych itp., Podobnie jak w przypadku spaceru, musisz filtrować wyniki. Oto przykład sprawdzania zrzutów rdzenia.

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) 

Albo

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

Brzmi jak przedwczesny optymalizacji dla mnie. Zerknąłem na źródło (http://hg.python.org/cpython/file/d01208ba482f/Lib/glob.py i http://hg.python.org/cpython/file/d01208ba482f/Lib/os.py) i zobacz, że obie funkcje polegają na 'os.listdir' i' os.isdir', więc moje jelito mówi mi, że nie zdobędziesz wiele takich czy innych rzeczy. (Jednakże, jak wskazano w dwóch z poniższych odpowiedzi, 'os.walk' recurses nad podkatalogami i' glob.iglob' nie ma, więc nie ma sensu porównywać). Jeśli masz problem z wydajnością, zrób profil dla kilku podejść. W przeciwnym razie po prostu napisz wyraźny kod. –

Odpowiedz

13

zrobiłem badania na małej podręcznej stron internetowych w 1000 katalogów. Zadanie polegało na zliczeniu całkowitej liczby plików w katalogach. Wyjście jest:

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

Jak widać, os.listdir jest najszybszy od trzech.I glog.glob jest nadal szybsze niż os.walk dla tego zadania.

Źródło:

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

Jeśli trzeba recurse przez podkatalogi, należy os.walk. W przeciwnym razie, wydaje mi się, że łatwiej byłoby użyć glob.iglob lub os.listdir.

+1

+1. Szczególnie dla wskazania, że ​​jedna funkcja powtarza się przez podkatalogi, podczas gdy druga nie. –

+0

@aculich. Dziękuję za poprawienie mnie. –

+3

@Steven, globalny wzór '/ path/to/*/core' używa' * 'jako symbolu wieloznacznego. 'glob' zastąpi' * 'tylko jednym katalogiem. Wciąż nie * rekursuje * do wszystkich podkatalogów. – unutbu

1

Możesz używać os.walk i nadal używać dopasowywania w stylu globalnym.

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

Nie wiesz, o prędkości, ale oczywiście od os.walk jest rekurencyjne, robią różne rzeczy.

10

Nie marnuj czasu na optymalizację przed pomiarem/profilowaniem. Skoncentruj się na tym, aby Twój kod był prosty i łatwy w utrzymaniu.

Na przykład w kodzie prekompilujesz RE, co nie daje żadnego zwiększenia prędkości, ponieważ moduł re ma wewnętrzny re._cache prekompilowanych RE.

  1. Keep it simple
  2. jeśli jest powolny, a następnie profil
  3. gdy wiesz dokładnie, co musi być zoptymalizowane zrobić kilka poprawek i zawsze udokumentować

uwaga, że ​​niektóre optymalizacji zrobić kilka lata wcześniej sprawiają, że kod działa wolniej w porównaniu do kodu "niezoptymalizowanego". Dotyczy to w szczególności nowoczesnych języków opartych na JIT.

+1

+1, aby uzyskać porady dotyczące optymalizacji. –

+7

-1. OP wspomniał o "dużym dysku". Kod jest oczywiście już prosty. Ponadto OP wydaje się być na etapie optymalizacji. To jest plaga na tyle, aby odrzucić pytania dotyczące wydajności z czymś w rodzaju "przedwczesne optymalizacje są korzeniami blabla" (które są w rzeczywistości błędnymi cytatami Knutha). – kgadek

+4

-1 Optymalizacja jest ważna w rzeczywistym (profesjonalnym) świecie, gdzie sprawy często mają bardzo dużą skalę. nie tylko ślepo kręci optymalizację bez żadnego racjonalnego uzasadnienia. – Julius

0

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

myślę nawet glob będzie trzeba jeszcze os.walk, chyba że wiesz jak głęboko bezpośrednio drzewo podkatalogu.

Przy okazji. w glob documentation mówi:

„*, oraz zakresy znaków wyrażone w [] będzie poprawnie dopasowanych Odbywa się to za pomocą os.listdir() i fnmatch.fnmatch() funkcje”.

Chciałbym po prostu iść z

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