2012-01-19 11 views
19

Я возился с файлами в python на большом жестком диске. Я смотрел на os.walk и glob. Обычно я использую os.walk, поскольку я нахожу его намного опрятным и, кажется, быстрее (для обычных каталогов размера).Быстрее для oswalk или glob?

У кого-нибудь есть опыт с ними обоими и может сказать, что более эффективно? Как я уже сказал, glob кажется медленнее, но вы можете использовать подстановочные знаки и т. Д., Как и при прогулке, вам нужно фильтровать результаты. Вот пример поиска основных дампов.

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) 

Или

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

Походит преждевременной оптимизации для меня. Я взглянул на источник (http://hg.python.org/cpython/file/d01208ba482f/Lib/glob.py и http://hg.python.org/cpython/file/d01208ba482f/Lib/os.py) и убедитесь, что обе функции опираются на 'os.listdir' и' os.isdir', поэтому моя кишка говорит мне, что вы не получите многого в том или ином виде. (Однако, как указано в двух из приведенных ниже ответов, 'os.walk' рекурсирует над подкаталогами, а' glob.iglob' - нет, поэтому сравнивать не имеет смысла). Если у вас заканчивается проблема с производительностью, прокомментируйте несколько подходов. В противном случае просто напишите чистый код. –

ответ

13

Я сделал исследование на небольшой кэш веб-страниц в 1000 директорий. Задача состояла в том, чтобы подсчитать общее количество файлов в каталогах. Выход:

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

Как вы видите, os.listdir является быстрый из трех.И glog.glob все еще быстрее, чем os.walk для выполнения этой задачи.

Источник:

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

Если вам нужна рекурсия через подкаталоги, используйте os.walk. В противном случае, я думаю, было бы проще использовать glob.iglob или os.listdir.

+1

+1. Специально для указания, что одна функция рекурсирует через подкаталоги, а другая - нет. –

+0

@aculich. Спасибо за исправление. –

+3

@Steven, шаблон glob '/ path/to/*/core' использует' * 'в качестве подстановочного знака. 'glob' заменит' * 'только одним каталогом. Он все еще не рекурсирует * через все подкаталоги. – unutbu

1

Вы можете использовать os.walk и по-прежнему использовать сопоставление glob-style.

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

Не уверен, что скорость, но, очевидно, так как os.walk является рекурсивным, они делают разные вещи.

10

Не тратьте время на оптимизацию перед измерением/профилированием. Сосредоточьтесь на том, чтобы сделать ваш код простым и удобным в обслуживании.

Например, в вашем коде вы предварительно компилируете RE, который не дает вам какого-либо повышения скорости, потому что модуль re имеет внутренний re._cache из предварительно скомпилированных REs.

  1. Держите его просто
  2. , если это медленно, то профиль
  3. когда вы точно знаете, что должно быть оптимизировано сделать некоторые хитрости и всегда документировать его

Обратите внимание, что некоторые оптимизации сделали несколько лет назад может сделать код медленнее по сравнению с «неоптимизированным» кодом. Это особенно касается современных языков, основанных на JIT.

+1

+1 за хороший совет о том, когда нужно оптимизировать. –

+7

-1. ОП упомянул «большой диск». Кроме того, код, очевидно, уже прост. Более того, ОП, похоже, находится на стадии оптимизации. Это чума на то, чтобы отбросить вопросы, связанные с производительностью, с чем-то вроде «преждевременных оптимизаций - это корень блабли» (которые на самом деле являются неверными цитатами Кнута). – kgadek

+4

-1 Оптимизация важна в реальном (профессиональном) мире, где вещи часто находятся в очень больших масштабах. не просто слепо разделить оптимизацию без какой-либо разумной причины – Julius

0

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

Я думаю, что даже с Glob вы все равно должны os.walk, если вы не знаете непосредственно, насколько глубоко ваш подкаталог дерево.

КПП. в glob documentation он говорит:

"? *, и диапазоны символов, выраженные с помощью [] будут правильно -им Это делается с помощью os.listdir() и fnmatch.fnmatch() функции."

я бы просто пойти с

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