Переопределение os.walk для возврата объекта генератора в качестве третьего элемента

При проверке эффективности os.walk, Я создал 6,00,000 файлы со строкой Hello <number> (где число - это просто число, указывающее номер файла в каталоге), например, содержимое файлов в каталоге будет выглядеть так:

File Name | Contents
1.txt     | Hello 1
2.txt     | Hello 2
.
.
600000.txt|Hello 600000

Теперь я запустил следующий код:-

a= os.walk(os.path.join(os.getcwd(),'too_many_same_type_files')) ## Here, I am just passing the actual path where those 6,00,000 txt files are present
print a.next()

Проблема, которую я чувствовал, состояла в том, что a.next() занимает слишком много времени и памяти, потому что третий пункт, который a.next() вернул бы список файлов в каталоге (который имеет 600000 элементов). Итак, я пытаюсь найти способ уменьшить сложность пространства (по крайней мере) путем a.next() вернуть объект генератора в качестве 3-го элемента кортежа вместо списка имен файлов.

Было бы хорошей идеей уменьшить сложность пространства?

3 ответа

Решение

Как уже упоминалось, 600000 файлов в каталоге - плохая идея. Сначала я думал, что на самом деле нет способа сделать это из-за того, как вы получаете доступ к списку файлов, но оказывается, что я ошибаюсь. Вы можете использовать следующие шаги для достижения того, что вы хотите:

  1. Использовать подпроцесс или os.system звонить ls или же dir (в какой бы ОС вы ни находились). Направьте вывод этой команды во временный файл (скажем, /tmp/myfiles или что-то. В Python есть модуль, который может вернуть вам новый tmp файл).

  2. Откройте этот файл для чтения в Python.

  3. Файловые объекты являются итеративными и будут возвращать каждую строку, поэтому, если у вас есть только имена файлов, все будет в порядке.

Это хорошая идея, именно так работает базовый C API!

Если вы можете получить доступ к readdir, вы можете сделать это: к сожалению, это не предоставляется напрямую Python.

Этот вопрос показывает два подхода (оба с недостатками).

Более чистым подходом было бы написать модуль на C, чтобы показать желаемую функциональность.

os.walk звонки listdir() под капотом, чтобы извлечь содержимое корневого каталога, затем приступает к разделению возвращенного списка элементов на dirs и non-dirs.

Чтобы достичь того, что вы хотите, вам нужно копать намного ниже и реализовать не только свою собственную версию walk() но и альтернатива listdir() который возвращает генератор. Обратите внимание, что даже тогда вы не сможете предоставить независимые генераторы для каталогов и файлов, если вы не сделаете два отдельных вызова для измененных listdir() и фильтровать результаты на лету.

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

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