Быстрый метод сканирования файлов / каталогов для Windows? - PullRequest
3 голосов
/ 29 декабря 2008

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

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

Есть идеи по ускорению сканирования файлов? Вот мой код на Python, но имейте в виду, что я совсем не женат на os.walk и совершенно готов использовать другие API (в том числе собственные API для Windows), если есть лучшие альтернативы.

for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        ...

Я должен также отметить, что я понимаю, что код Python, вероятно, не может быть ускорен так сильно; Я особенно заинтересован в любых нативных API, которые обеспечивают лучшую скорость.

Ответы [ 9 ]

3 голосов
/ 29 декабря 2008

Похоже, что os.walk был значительно улучшен в Python 2.5, так что вы можете проверить, используете ли вы эту версию.

Кроме этого, кто-то уже сравнил скорость os.walk с ls и заметил явное продвижение последнего, но не в диапазоне, который фактически оправдывал бы его использование.

3 голосов
/ 29 декабря 2008

Что ж, я ожидаю, что эта задача будет сильно связана с вводом / выводом. Таким образом, оптимизация на стороне Python будет совершенно неэффективной; единственная оптимизация, о которой я мог подумать, - это какой-то другой способ доступа к файлам / листингам, чтобы уменьшить реальное чтение из файловой системы. Это, конечно, требует глубоких знаний о файловой системе, которых у меня нет, и я не ожидаю, что разработчик python будет иметь при реализации os.walk.

А как насчет порождения командной строки, а затем выдачи 'dir' и анализа результатов? Это может быть немного излишним, но если повезет, «dir» предпринимает некоторые усилия для такой оптимизации.

2 голосов
/ 31 октября 2013

Используйте модуль Scandir Python (ранее Betwalk) на GitHub Беном Хойтом.

http://github.com/benhoyt/scandir

Это намного быстрее, чем Python Walk, но использует тот же синтаксис. Просто импортируйте scandir и измените os.walk () на scandir.walk (). Вот и все. Это самый быстрый способ просмотра каталогов и файлов в python.

2 голосов
/ 29 декабря 2008

Возможно, вы захотите взглянуть на код для некоторых систем контроля версий Python, таких как Mercurial или Bazaar. Они посвятили много времени поиску способов быстрого обхода дерева каталогов и обнаружения изменений (или «поиска базовой статистики о файлах»).

1 голос
/ 14 сентября 2015

Python 3.5 только что представлен os.scandir (см. PEP-0471 ), что позволяет избежать ряда необязательных системных вызовов, таких как stat() и GetFileAttributes(), чтобы обеспечить значительно более быстрый итератор файловой системы.

os.walk() теперь будет реализован с использованием os.scandir() в качестве итератора, и поэтому вы должны увидеть потенциально значительные улучшения производительности, продолжая использовать os.walk().


Пример использования:

for entry in os.scandir(path):
   if not entry.name.startswith('.') and entry.is_file():
       print(entry.name)
1 голос
/ 29 декабря 2008

Мне интересно, можете ли вы сгруппировать операции ввода-вывода.

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

Если ваша ОС хранит эти две данные в разных местах (структура каталогов в одном месте, статистика файлов в другом), то это может быть существенной оптимизацией.

Во всяком случае, это то, что я попробую, прежде чем копать дальше.

1 голос
/ 29 декабря 2008

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

Например, ниже всего на волосок быстрее, чем os.walk.

import os
import stat

listdir= os.listdir
pathjoin= os.path.join
fstat= os.stat
is_dir= stat.S_ISDIR
is_reg= stat.S_ISREG
def yieldFiles( path ):
    for f in listdir(path):
        nm= pathjoin( path, f )
        s= fstat( nm ).st_mode
        if is_dir( s ):
            for sub in yieldFiles( nm ):
                yield sub
        elif is_reg( s ):
            yield f
        else:
            pass # ignore these

Следовательно, накладные расходы должны быть в самом модуле os. Вам придется прибегнуть к прямым вызовам Windows API.

Посмотрите на Python для расширений Windows .

0 голосов
/ 31 декабря 2008

Это только частичная помощь, больше похожая на указатели; однако:

Я считаю, что вам нужно сделать следующее:

fp = open("C:/$MFT", "rb")

с использованием учетной записи, которая имеет разрешения SYSTEM, потому что даже как администратор вы не можете открыть «главную таблицу файлов» (вид таблицы inode) файловой системы NTFS. После того, как вы преуспеете в этом, вам просто нужно будет найти в Интернете информацию, объясняющую структуру каждой записи файла (я думаю, что обычно это 1024 байта на файл на диске, который включает в себя основной путь файла) для сверхвысоких скоростей чтения структуры диска.

0 голосов
/ 29 декабря 2008

Модуль os.path также имеет функцию обхода дерева каталогов. Я никогда не проводил никаких тестов, но вы можете попробовать. Однако я не уверен, что в Python есть более быстрый способ, чем os.walk / os.path.walk.

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