Создание собственного модуля find

sozdanie sobstvennogo modulya find Законченные системные программы

Но если команда find доступна не на всех ваших компьютерах, не волнуйтесь — ее легко можно реализовать на языке Python. Ранее в стандартной библиотеке Python имелся модуль find, который я часто использовал. И хотя этот модуль был удален из библиотеки где-то между вторым и третьим изданиями этой книги, в стандартной библиотеке появилась функция os.walk, которая способна упростить создание собственного модуля find. Вместо того чтобы оплакивать исчезновение модуля, я решил потратить 10 минут и написать свой эквивалент.

В примере 6.13 представлена утилита find, реализованная на языке Python, которая выбирает все имена файлов в каталоге, соответствующие шаблону. В отличие от glob.glob, функция find.find автоматически выполняет поиск во всем дереве каталогов. А в отличие от структуры обхода os.walk, результаты find.find можно трактовать, как простую линейную группу строк.

Пример 6.13. PP4E\Tools\find.py

#!/usr/bin/python

############################################################################## Возвращает все имена файлов, соответствующие шаблону в дереве каталогов;

собственная версия модуля find, ныне исключенного из стандартной библиотеки: импортируется как PP4E.Tools.find”; похож на оригинал, но использует цикл os.walk, не поддерживает возможность обрезания ветвей подкаталогов и может запускаться как самостоятельный сценарий;

find() — функция-генератор, использующая функцию-генератор os.walk(), возвращающая только имена файлов, соответствующие шаблону: чтобы получить весь список результатов сразу, используйте функцию findlist();

##############################################################################

import fnmatch, os

def find(pattern, startdir=os.curdir):

for (thisDir, subsHere, filesHere) in os.walk(startdir):

for name in subsHere + filesHere:

if fnmatch.fnmatch(name, pattern):

fullpath = os.path.join(thisDir, name) yield fullpath

def findlist(pattern, startdir=os.curdir, dosort=False): matches = list(find(pattern, startdir)) if dosort: matches.sort() return matches

if __name__ == ‘__main__’: import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print(name)

Вроде бы немного делает этот программный код — по сути, он лишь несколько расширяет возможности функции os.walk, — но его функция find позволяет получить те же результаты, что давал ранее существовавший в стандартной библиотеке модуль find и одноименная утилита в Unix. Кроме того, этот модуль является более переносимым решением, и пользоваться им намного проще, чем повторять его программный код всякий раз, когда потребуется выполнить поиск. Поскольку этот файл можно использовать и как сценарий, и как библиотечный модуль, его можно применять как инструмент командной строки и вызывать из других программ.

Например, чтобы обработать все файлы с программным кодом на языке Python, находящиеся в дереве каталогов, с корнем на один уровень выше текущего рабочего каталога, достаточно просто запустить приведенную ниже команду в окне консоли. Запустите эту команду у себя, чтобы увидеть ее в действии, — в данном примере стандартный вывод сценария передается по конвейеру команде more, обеспечивающей возможность постраничного просмотра результатов, но его точно так же можно передать любой другой программе обработки, которая читает входные данные из стандартного потока ввода:

C:\\PP4E\Tools> python find.py *.py .. | more

..\LaunchBrowser.py

..\Launcher.py

..\__init__.py

..\Preview\attachgui.py

..\Preview\customizegui.py

…множество строк опущено…

Чтобы получить еще больший контроль, выполните следующий программный код на языке Python в сценарии или в интерактивной оболочке. При таком подходе к найденным файлам можно применять любые операции, доступные в языке Python:

C:\\PP4E\System\Filetools> python

>  >> from PP4E.Tools import find # или просто import find, если

>  >> for filename in find.find(‘*.py’, ‘..’): # модуль находится в cwd

if ‘walk’ in open(filename).read():

print(filename)

..\Launcher.py

..\System\Filetools\bigext-tree.py

..\System\Filetools\bigpy-path.py

..\System\Filetools\bigpy-tree.py

..\Tools\cleanpyc.py

..\Tools\find.py

..\Tools\visitor.py

Обратите внимание, что в данном случае отпала необходимость во вложенных циклах, необходимых при использовании функции os.walk, когда требуется получить список имен файлов, соответствующих шаблону, — во многих случаях такой подход концептуально выглядит проще. Заметьте также, что функция поиска является функцией-генератором, благодаря чему сценарию не приходится ждать, пока не будут выбраны все соответствующие имена файлов, — функция os.walk поставляет результаты для каждого каталога в отдельности, а функция find.find поставляет имена файлов, выбирая их из этих результатов.

Ниже приводится более сложный пример использования модуля find: следующая команда выводит все имена файлов с программным кодом на языке Python, находящиеся в дереве каталогов с корнем в C:\temp\ PP3E, начинающиеся с символа q или t. Обратите внимание, что find возвращает полные пути к файлам, начиная от указанного каталога:

C:\\PP4E\Tools> find.py [qx]*.py C:\temp\PP3E

C:\temp\PP3E\Examples\PP3E\Database\SQLscripts\querydb.py C:\temp\PP3E\Examples\PP3E\Gui\Tools\queuetest-gui-class.py C:\temp\PP3E\Examples\PP3E\Gui\Tools\queuetest-gui.py C:\temp\PP3E\Examples\PP3E\Gui\Tour\quitter.py

C:\temp\PP3E\Examples\PP3E\Internet\Other\Grail\Question.py

C:\temp\PP3E\Examples\PP3E\Internet\Other\XML\xmlrpc.py C:\temp\PP3E\Examples\PP3E\System\Threads\queuetest.py

А ниже приводится программный код Python, который выполняет тот же поиск, но при этом выводит только имена файлов без путей к ним и размеры файлов:

C:\\PP4E\Tools> python

>  >> import os

>  >> from find import find

>  >> for name in find(‘[qx]*.py’, r’C:\temp\PP3E’):

print(os.path.basename(name), os.path.getsize(name))

querydb.py 635

queuetest-gui-class.py 1152 queuetest-gui.py 963 quitter.py 801

Question.py 817

xmlrpc.py 705

queuetest.py 1273

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий