Быстрее os.walk или шар? - PullRequest
       32

Быстрее os.walk или шар?

27 голосов
/ 19 января 2012

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

Кто-нибудь имел опыт работы с ними обоими и мог бы сказать, что более эффективно?Как я уже сказал, 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)

Ответы [ 4 ]

22 голосов
/ 19 декабря 2014

Я провел исследование небольшого кэша веб-страниц в 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)
10 голосов
/ 19 января 2012

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

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

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

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

2 голосов
/ 19 января 2012

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

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

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

0 голосов
/ 26 апреля 2014

*, ?, 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 говорится:

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

Я бы просто пошел с

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