2015-09-08 5 views
4

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

Это код, который я в настоящее время используют:

def find_children(tickstore): 
    children = [] 
    dir_list = os.walk(tickstore) 
    for i in dir_list: 
     children.append(i[0]) 
    return children 

Я сделал некоторый анализ по нему:

dir_list = os.walk(tickstore) запускается мгновенно, если я ничего не делаю с dir_list, то эта функция завершается мгновенно.

Это итерация свыше dir_list, что занимает много времени, даже если я не делаю append ничего, просто повторяя его, это то, что требует времени.

Tickstore большое хранилище данных, с ~ 10 000 справочников.

В настоящее время для выполнения этой функции требуется около 35 минут.

Есть ли способ ускорить его?

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

+2

'return [dir for dir, _, _ in os.walk (tickstore)]' может быть немного более эффективным, но доступ к жесткому диску относительно невелик в целом. – jonrsharpe

+0

Что вы делаете с созданным списком детей? Может быть, вам даже не нужен весь список, поскольку следующая вещь, которую вы делаете, - это фильтровать/сканировать последовательность вещей? –

+0

Я бы предположил еще медленнее, когда он обращается к сетевому диску? –

ответ

9

Да: используйте Python 3.5 (который по-прежнему в настоящее время является RC, но should be out momentarily). В Python 3.5, os.walk был переписан, чтобы быть более эффективным.

Эта работа выполнена в составе PEP 471.

Выдержки из PEP:

Python встроенный os.walk() значительно медленнее, чем это должно быть , потому что - в дополнение к вызову os.listdir() каждого каталога - он выполняет stat() системный вызов или GetFileAttributes() для каждого файла, чтобы определить, является ли запись каталогом или нет.

Но основная система вызывает - FindFirstFile/FindNextFile на Windows, и readdir на системах POSIX - уже сказать вам, что файлы возвращаются ли каталоги или нет, поэтому никаких других системных вызовов не нужно. Кроме того, системные вызовы Windows возвращают всю информацию для объекта stat_result на запись в каталоге, например размер файла и время последней модификации.

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

На практике удаление всех тех, дополнительные системные вызовы делает os.walk() около 8-9 раз быстрее на Windows, , и примерно в 2 раза быстрее, чем POSIX-системы. Поэтому мы не говорим о микро-оптимизации.См. Здесь .

+4

(1) вы могли бы использовать библиотеку '' scandir' (https://github.com/benhoyt/scandir) для более ранних версий Python (2) [не ожидайте повышения производительности в системах POSIX (по сравнению с 'os.fwalk() ')] (http://bugs.python.org/issue22524). Измерьте это. – jfs

3

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

Улучшение предлагается в PEP 471 и должно скоро появиться на Python 3.5. Тем временем вы можете использовать пакет scandir, чтобы получить те же преимущества в Python. 2.7

1

Метод оптимизации в python2.7, используйте scandir.walk() вместо os.walk(), параметры точно такие же.

import scandir 
directory = "/tmp" 
res = scandir.walk(directory) 
for item in res: 
    print item 

PS: Так же, как @recoup упоминалось в комментариях, scandir должен быть установлен перед использованием в python2.7.

+0

[scandir нуждается в установке через PyPI] (https://pypi.python.org/pypi/scandir) в версии 2.7, это только в стандартной библиотеке от Python 3.5. См. Предложение и то, как он работает на https://www.python.org/dev/peps/pep-0471/ – rcoup

+0

Да, спасибо за напоминание, scandir необходимо установить с помощью программы install install scandir перед импортом. – buxizhizhoum