Лучший способ получить список файлов большой директории на python?

У меня безумный большой каталог. Мне нужно получить список файлов через Python.

В коде мне нужно получить итератор, а не список. Так что это не работа:

os.listdir
glob.glob  (uses listdir!)
os.walk

Я не могу найти хорошую библиотеку. Помогите! Может быть, C++ lib?

7 ответов

Решение

Если у вас есть каталог, который слишком велик для быстрого чтения libc readdir(), вы, вероятно, захотите взглянуть на вызов ядра getdents () ( http://www.kernel.org/doc/man-pages/online/pages/man2/getdents.2.html). Я столкнулся с подобной проблемой и написал длинный пост в блоге об этом.

http://www.olark.com/spw/2011/08/you-can-list-a-directory-with-8-million-files-but-not-with-ls/

По сути, readdir() читает только 32 КБ записей каталога за раз, и поэтому, если у вас много файлов в каталоге, readdir() займет очень много времени.

Для Python 2.X

import scandir
scandir.walk()

для питона 3.5+

os.scandir()

https://www.python.org/dev/peps/pep-0471/

https://pypi.python.org/pypi/scandir

Я нашел эту библиотеку полезной: https://github.com/benhoyt/scandir.

Кто-то построил модуль Python на основе этой статьи, которая завершает getdents. Кстати, я знаю, что этот пост старый, но вы можете использоватьscandir(и я сделал это с каталогами с 21 миллионом файлов). Ходьба - это слишком медленно, хотя это тоже генератор, но слишком много накладных расходов.

Этот модуль кажется интересной альтернативой. Не использовал его, но он основал это на статье LS с 8 миллионами файлов, упомянутой выше. Читая код, думая, что это было бы весело и быстрее использовать.

Также позволяет настраивать буфер, не заходя напрямую в C.

https://github.com/ZipFile/python-getdents И через pip и pypi, хотя я рекомендую прочитать документы.

https://pypi.org/project/getdents/

Я нашел эту библиотеку очень быстро.
https://pypi.org/project/scandir/
Я использовал приведенный ниже код из этой библиотеки, он работал как шарм.

def subdirs(path):
"""Yield directory names not starting with '.' under given path."""
for entry in os.scandir(path):
    if not entry.name.startswith('.') and entry.is_dir():
        yield entry.name

Вы должны использовать генератор. Эта проблема обсуждается здесь: http://bugs.python.org/issue11406

Я думаю, что использование opendir будет работать, и есть пакет python: http://pypi.python.org/pypi/opendir/0.0.1 который обертывает его через pyrex

http://docs.python.org/release/2.6.5/library/os.html

>>> import os
>>> type(os.walk('/'))
<type 'generator'>

Как насчет glob.iglob? Это шар итератора.

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