Функция os.walk сама осуществляет обход дерева — нам остается лишь реализовать тело цикла, выполняющее необходимые действия. Но иногда большей гибкости можно достичь, реализовав обход дерева самостоятельно, при этом почти не приложив лишних усилий. В следующем сценарии представлена другая реализация вывода содержимого каталога с использованием рекурсивной функции обхода (функция, которая вызывает саму себя, чтобы повторить операции). Функция mylister в примере 4.5 очень похожа на функцию lister из примера 4.4, но создает списки имен файлов с помощью os.listdir и вызывает саму себя рекурсивно, чтобы спуститься в подкаталоги.
Пример 4.5. PP4E\System\Filetools\lister_recur.py
# выводит список файлов в дереве каталогов с применением рекурсии
import sys, os
def mylister(currdir):
print(‘[‘ + currdir + ‘]’)
for file in os.listdir(currdir): # генерирует список файлов
path = os.path.join(currdir, file) # добавить путь к каталогу if not os.path.isdir(path):
print(path) else:
mylister(path) # рекурсивный спуск в подкаталоги
if __name__ == ‘__main__’:
mylister(sys.argv[1]) # имя каталога в командной строке
Как обычно, этот файл можно импортировать или запускать как самостоятельный сценарий. Тот факт, что результатом его работы является печать текста, можно отнести к его недостаткам при его использовании в качестве импортируемого инструмента, если только его стандартный поток вывода не перехватывается в другой программе.
Когда этот файл запускается как самостоятельный сценарий, он воспроизводит почти те же результаты, что и пример 4.4; почти, но не полностью — в отличие от версии на основе функции os.walk, рекурсивная версия не обязует пройти все файлы на текущем уровне, прежде чем спуститься в подкаталоги. Можно было бы обойти список имен файлов дважды (чтобы сначала отобрать файлы), но в данной реализации порядок обхода определяется результатами, возвращаемыми функцией os.listdir. Для многих случаев такой порядок обхода может оказаться неприемлемым:
C:\…\PP4E\System\Filetools> python lister_recur.py C:\temp\test [C:\temp\test] [C:\temp\test\parts]
C:\temp\test\parts\part0001
C:\temp\test\parts\part0002
C:\temp\test\parts\part0003
C:\temp\test\parts\part0004 C:\temp\test\random.bin C:\temp\test\spam.txt
C:\temp\test\temp.bin
C:\temp\test\temp.txt
Мы еще воспользуемся большей частью приемов, приведенных в этом разделе, в главе 6 и далее в книге. Например, приведенные выше приемы обхода деревьев будут использованы в сценариях копирования и сравнения деревьев каталогов. По ходу изложения вы увидите эти инструменты в действии. Кроме того, в главе 6 мы реализуем утилиту find, объединяющую в себе обход дерева каталогов с помощью os.walk и поиск имен файлов по шаблону с помощью glob.glob.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011