Более быстрый способ хождения по Директории вместо os.listdir? - PullRequest
14 голосов
/ 02 июля 2010

Я пытаюсь улучшить производительность elfinder, файлового менеджера на основе ajax (elRTE.ru).

Он использует os.listdir в рекурсиве для рекурсивного просмотра всех каталогов и снижения производительности (например,перечисление каталога с 3000 + файлами занимает 7 секунд) ..

Я пытаюсь улучшить производительность, вот его функция ходьбы:

        for d in os.listdir(path):
            pd = os.path.join(path, d)
            if os.path.isdir(pd) and not os.path.islink(pd) and self.__isAccepted(d):
                tree['dirs'].append(self.__tree(pd))

Мои вопросы:

  1. Если бы я изменил os.walk вместо os.listdir, это улучшит производительность?
  2. как насчет использования dircache.listdir ()?кэшировать ВСЕ содержимое каталога / подкаталога при первоначальном запросе и возвращать результаты кэширования, если нет новых загруженных файлов или нет изменений в файле?
  3. Существует ли какой-либо другой способ обхода каталога, более быстрый?
  4. Любой другой файловый браузер на стороне сервера, который быстро написан на python (но я предпочитаю сделать этот быстрый)?

Ответы [ 7 ]

17 голосов
/ 19 января 2011

Я просто пытался выяснить, как ускорить os.walk в большой файловой системе (350 000 файлов распределены в пределах 50 000 каталогов).Я использую Linux-систему с файловой системой ext3.Я обнаружил, что есть способ ускорить это для моего случая.

В частности, используя обход сверху вниз, каждый раз, когда os.walk возвращает список из более чем одного каталога, я использую os.stat дляполучить номер инода каждого каталога и отсортировать список каталогов по номеру инода.Это заставляет ходить, в основном, посещать подкаталоги в порядке inode, что уменьшает количество обращений к диску.

В моем случае это ускорило мой полный просмотр каталога с 18 минут до 13 минут ...

11 голосов
/ 13 ноября 2015

Вы проверяли scandir (ранее betterwalk )? Сам не пробовал, но здесь есть обсуждение и еще одно здесь . Он утверждает, что имеет ускорение в 3-10 раз на MacOSX / Linux и 7-50 в Windows, избегая избыточных вызовов os.stat (). Он также теперь включен в стандартную библиотеку Python 3.5.

Встроенный в Python os.walk () значительно медленнее, чем нужно быть, потому что - в дополнение к вызову listdir () для каждого каталога - он вызывает stat () для каждого файла, чтобы определить, является ли имя файла каталог или нет. Но оба FindFirstFile / FindNextFile на Windows и readdir в Linux / OS X уже сообщает вам, возвращены ли файлы каталоги или нет, так что никаких дополнительных системных вызовов stat не требуется. В Короче говоря, вы можете уменьшить количество системных вызовов с 2N до N, где N - общее количество файлов и каталогов в дереве.

На практике удаление всех этих дополнительных системных вызовов делает os.walk () примерно в в 7-50 раз быстрее в Windows и в 3-10 раз быстрее в Windows Linux и Mac OS X .

Из файла проекта readme .

5 голосов
/ 02 июля 2010

Вы должны измерять непосредственно на машинах (ОС, файловых системах и их кэшах и т. Д.), Которые вас интересуют, вне зависимости от того, является ли os.walk быстрее, чем os.listdir на конкретной и совершенно другой машине / ОС / FS. расскажу вам очень мало о производительности на вашем .

Не уверен, что вы подразумеваете под cachedir.listdir - нет стандартного библиотечного модуля / функции с таким именем. listdir уже читает все каталоги за один раз (поскольку он должен сортировать результаты), как и os.walk (поскольку он должен отделять подкаталоги от файлов). Если, в зависимости от вашей платформы, у вас есть быстрый способ получения уведомлений об изменениях файлов / каталогов, то, вероятно, стоит создать дерево один раз и редактировать его постепенно, по мере появления уведомлений об изменениях ... но это зависит от относительной частоты изменений против запросов, что опять-таки полностью зависит от ваших конкретных условий применения.

3 голосов
/ 02 июля 2010

В заказе:

  • Я сомневаюсь, что вы увидите значительное ускорение между os.walk и os.listdir, поскольку оба зависят от базовой файловой системы. На самом деле, я подозреваю, что основная файловая система окажет большое влияние на скорость операции.

  • Любая операция кэширования будет выполняться значительно быстрее, чем попадание в файловую систему (по крайней мере, для второй и последующих проверок).

  • Вы всегда можете написать какую-нибудь утилиту (или вызвать команду оболочки), которая генерирует список каталогов вне Python и вызывает его через модуль subprocess. Но это немного сложно, и я бы обратился к этому решению, только если кеш оказался для вас неработоспособным.

  • Если вы не нашли файловый браузер в Cheeseshop , вы, вероятно, не найдете его.

1 голос
/ 05 апреля 2014

Вы ищете fsdir .Он написан на C и предназначен для работы с Python.Это намного быстрее, чем обход дерева по стандартным библиотекам Python

1 голос
/ 31 июля 2013

Как насчет этого в bash?

import subprocess
command = 'ls .... or something else'
subprocess.Popen([command] ,shell=True) 

В моем случае, когда менялись разрешения для тысяч файлов, это работало намного лучше.

0 голосов
/ 02 июля 2010

os.path.walk может повысить производительность по двум причинам:

1) Если вы можете прекратить ходить до того, как пройдете все, тогда это действительно будет быстрее, чем listdir, хотя это заметно только при работе с большими деревьями

2) Если вы перечисляете ОГРОМНЫЕ каталоги, то сделать список, возвращаемый listdir. , может быть дорого (не соответствует действительности, см. Комментарий Алекса ниже)

Тем не менее, это, вероятно, не будет иметь значения и на самом деле может быть медленнее из-за потенциально дополнительных накладных расходов, вызванных вызовом вашей функции visit и выполнением всех дополнительных упаковок и распаковок аргументов.

(Единственный способ ответить на этот вопрос - проверить его самостоятельно - это займет всего несколько минут)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...