Копирование деревьев каталогов с помощью классов (Visitor)

kopirovanie derevev katalogov s pomoshhju klassov visitor Законченные системные программы

Рассмотрим еще один случай использования классов-обходчиков. Когда я впервые написал сценарий cpall.py ранее в этой главе, я не понимал, как можно применить иерархию классов-обходчиков, с которой мы встретились выше, для копирования деревьев каталогов. При копировании необходимо выполнять обход сразу двух деревьев каталогов (оригинального и его копии), а visitor выполняет обход только одного дерева, используя функцию os.walk. Тогда мне казалось, что будет совсем не просто следить за тем, где находится сценарий в копии дерева.

Хитрость, до которой я в конце концов додумался, заключается в том, что следить за позицией в дереве копии вообще не требуется. Вместо этого сценарий в примере 6.22 просто замещает строку пути к каталогу «из» строкой пути к каталогу «в» и добавляет ее перед всеми именами каталогов, полученными от функции os.walk. В результате такой подмены получаются пути, куда должны быть скопированы оригинальные файлы и каталоги.

Пример 6.22. PP4E\Tools\visitor_cpall.py

Использование: “python \Tools\visitor_cpall.py fromDir toDir trace?” Действует подобно сценарию System\Filetools\cpall.py, но использует классы- обходчики и функцию os.walk; заменяет строку fromDir на toDir перед всеми именами, возвращаемыми обходчиком; предполагается, что изначально каталог toDir не существует;

import os

from visitor import FileVisitor # обходчик в каталоге

from PP4E.System.Filetools.cpall import copyfile # PP4E в пути поиска

class CpallVisitor(FileVisitor):

def __init__(self, fromDir, toDir, trace=True):

self.fromDirLen = len(fromDir) + 1

self.toDir = toDir

FileVisitor.__init__(self, trace=trace)

def visitdir(self, dirpath):

toPath = os.path.join(self.toDir, dirpath[self.fromDirLen:]) if self.trace: print(‘d’, dirpath, ‘=>’, toPath) os.mkdir(toPath) self.dcount += 1

def visitfile(self, filepath):

toPath = os.path.join(self.toDir, filepath[self.fromDirLen:]) if self.trace: print(‘f’, filepath, ‘=>’, toPath) copyfile(filepath, toPath) self.fcount += 1

if __name__ == ‘__main__’: import sys, time fromDir, toDir = sys.argv[1:3] trace = len(sys.argv) > 3 print(‘Copying…’) start = time.clock() walker = CpallVisitor(fromDir, toDir, trace) walker.run(startDir=fromDir) print(‘Copied’, walker.fcount, ‘files,’, walker.dcount, ‘directories’, end=’ ‘)

print(‘in’, time.clock() start, ‘seconds’)

Эта версия достигает почти той же цели, что и оригинал, но в ней сделано несколько допущений, чтобы упростить реализацию. Предполагается, что каталог «в» изначально не существует, а исключения, возникающие в процессе копирования, не игнорируются. Следующий пример демонстрирует копирование дерева примеров для предыдущего издания книги в Windows:

C:\\PP4E\Tools> set PYTHONPATH

PYTHONPATH=C:\Users\Mark\Stuff\Books\4E\PP4E\dev\Examples

C:\\PP4E\Tools> rmdir /S copytemp copytemp, Are you sure (Y/N)? y

C:\\PP4E\Tools> visitor_cpall.py C:\temp\PP3E\Examples copytemp Copying

Copied 1429 files, 186 directories in 11.1722033777 seconds

C:\\PP4E\Tools> fc /B copytemp\PP3E\Launcher.py

C:\temp\PP3E\Examples\PP3E\Launcher.py

Comparing files COPYTEMP\PP3E\Launcher.py and C:\TEMP\PP3E\EXAMPLES\PP3E\ LAUNCHER.PY FC: no differences encountered

Несмотря на то, что в этой версии выполняется дополнительная операция извлечения среза из строки, она действует так же быстро, как и оригинал (фактическое отличие можно списать на разницу в нагрузке на систему). Кроме того, эта версия позволяет проследить за всеми путями «из» и «в» в процессе обхода, если передать ей третий аргумент командной строки:

C:\\PP4E\Tools> rmdir /S copytemp copytemp, Are you sure (Y/N)? y

C:\\PP4E\Tools> visitor_cpall.py C:\temp\PP3E\Examples copytemp 1

Copying

d C:\temp\PP3E\Examples => copytemp\

f C:\temp\PP3E\Examples\README-root.txt => copytemp\README-root.txt

d C:\temp\PP3E\Examples\PP3E => copytemp\PP3E

…множество строк опущено: запустите этот сценарий у себя, чтобы увидеть вывод целиком…

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

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