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

Я возиться с поиском файлов в 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)

6 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

Btw. в документации Glob говорится:

"*,? и диапазоны символов, выраженные [], будут правильно сопоставлены. Это делается с помощью функций 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)

Часть, которая, кажется, никогда не упоминается при сравнении os.walk с любым другим методом, заключается в том, что он имеет другую функциональность. Scandir — это базовая реализация, которая имеет самую высокую производительность при простом доступе к содержимому каталога.Listdir предназначен для простого списка содержимого каталога.glob — это потенциально рекурсивная операция сопоставления с образцом.Walk — это рекурсивный обход каталога с полным контролем пользователя.

  • пользователь может решить, в каком порядке перемещаться, используя topdown=True|False
  • пользователь может обрезать дерево во время обхода (используя topdown=True), удаляя каталоги из списка подкаталогов для любого заданного каталога.
  • пользователь может выполнять произвольные действия с файлами и каталогами во время обхода.
  • комбинируя управление порядком обхода и удалением файлов, пользователь может использовать topdown=False и удалять файлы, а затем, если каталог пуст, каталог можно удалить.

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

Другие вопросы по тегам