Выгрузка локального дерева каталогов

vygruzka lokalnogo dereva katalogov Сценарии на стороне клиента

Оказывается, поддержка выгрузки подкаталогов осуществляется достаточно просто — требуется добавить только немного рекурсии и вызовы методов для создания удаленных каталогов. Сценарий выгрузки на сервер, представленный в примере 13.15, расширяет версию на основе классов, которую мы только что видели в примере 13.14, и осуществляет выгрузку всех подкаталогов, вложенных в пересылаемый каталог. Более того, он рекурсивно пересылает каталоги, находящиеся внутри подкаталогов, — все дерево каталогов, содержащееся внутри передаваемого каталога верхнего уровня, выгружается в целевой каталог на удаленном сервере.

С точки зрения организации программного кода пример 13.15 является простой адаптацией класса FtpTools из предыдущего раздела — в действительности мы просто реализовали подкласс с методом, выполняющим рекурсивную выгрузку. Как одно из следствий, мы бесплатно получаем инструменты, хранящие параметры настройки, проверяющие тип содержимого, выполняющие соединение с сервером и выгрузку — благодаря применению ООП часть работы оказалась выполненной еще до того, как мы к ней приступили.

Пример 13.15. PP4E\Internet\Ftp\Mirror\uploadall.py

#!/bin/env python

############################################################################ расширяет класс FtpTools, обеспечивая возможность выгрузки всех файлов и подкаталогов из локального дерева каталогов в удаленный каталог на сервере; поддерживает вложенные подкаталоги, но не поддерживает операцию cleanall (для этого необходимо анализировать листинги FTP, чтобы определять удаленные каталоги: смотрите сценарий cleanall.py); для выгрузки подкаталогов используется os.path.isdir(path), которая проверяет, является ли в действительности локальный файл каталогом, метод FTP().mkd(path) — для создания каталогов на сервере (вызов обернут инструкцией try, на случай если каталог уже существует на сервере), и рекурсия — для выгрузки всех файлов/каталогов внутри вложенного подкаталога.

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

import os, ftptools

class UploadAll(ftptools.FtpTools)

выгружает дерево подкаталогов целиком

предполагается, что каталог верхнего уровня уже существует на сервере def __init__(self):

self.fcount = self.dcount = 0

def getcleanall(self):

return False # даже не спрашивать

def uploadDir(self, localdir):

для каждого каталога в дереве выгружает простые файлы, производит рекурсивный вызов для подкаталогов localfiles = os.listdir(localdir)

for localname in localfiles:

localpath = os.path.join(localdir, localname)

print(‘uploading’, localpath, ‘to’, localname, end=’ ‘) if not os.path.isdir(localpath):

self.uploadOne(localname, localpath, localname) self.fcount += 1

else:

try:

self.connection.mkd(localname) print(‘directory created’)

except:

print(‘directory not created’) self.connection.cwd(localname) # изменить удаленный каталог self.uploadDir(localpath) # выгрузить локальный каталог

self.connection.cwd(‘..’) # вернуться обратно

self.dcount += 1

print(‘directory exited’)

if __name__ == ‘__main__’: ftp = UploadAll() ftp.configTransfer(site=’learning-python.com’, rdir=’training’, user=’lutz’) ftp.run(transferAct = lambda: ftp.uploadDir(ftp.localdir)) print(‘Done:’, ftp.fcount, ‘files and’, ftp.dcount, ‘directories uploaded.’)

Как и сценарий выгрузки плоских каталогов, этот сценарий может выполняться на любом компьютере с Python и сокетами и осуществлять выгрузку на любой компьютер, где выполняется сервер FTP. Я запускаю его на своем ноутбуке и на других серверах через Telnet или SSH, чтобы выгрузить сайты на сервер моего интернет-провайдера.

Центральным пунктом в этом сценарии является вызов функции os.path. isdir в самом начале. Если эта проверка обнаруживает подкаталог в текущем локальном каталоге, с помощью метода connection.mkd на удаленном сервере создается одноименный каталог, с помощью connection.cwd выполняется вход в него и рекурсивный спуск в подкаталог на локальном компьютере (рекурсия здесь совершенно необходима, так как дерево каталогов может иметь произвольную структуру и глубину). Как и все методы объекта FTP, методы mkd и cwd посылают команды FTP удаленному серверу. Выйдя из локального подкаталога, выполняется выход из удаленного подкаталога cwd(‘..’), чтобы подняться в родительский каталог на сервере, и обход файлов продолжается — возврат из рекурсивного вызова автоматически восстанавливает местоположение в текущем каталоге. Остальная часть сценария примерно совпадает с первоначальным вариантом.

В целях экономии места я оставляю более глубокое изучение этого варианта в качестве упражнения для читателя. Чтобы получить более полное представление, попробуйте изменить этот сценарий, чтобы он не полагался больше на наличие на сервере каталога верхнего уровня. Как обычно в мире программного обеспечения, данную особенность можно реализовать различными способами.

Ниже приводится пример вывода сценария uploadall, запущенного для выгрузки сайта, содержащего несколько уровней вложенности подкаталогов, который я сопровождаю с помощью инструментов конструирования сайтов. Он напоминает вывод сценария выгрузки плоского каталога (чего вполне можно было ожидать, учитывая, что данный сценарий использует большую часть того же программного кода через механизм наследования), но обратите внимание, что попутно он выгружает вложенные подкаталоги:

C:\\PP4E\Internet\Ftp\Mirror> uploadall.py Website-Training

Password for lutz on learning-python.com: connecting

uploading Website-Training\2009-public-classes.htm

to 2009-public-classes.htm text

uploading Website-Training\2010-public-classes.html

to 2010-public-classes.html text

uploading Website-Training\about.html to about.html text

uploading Website-Training\books to books directory created

uploading Website-Training\books\index.htm to index.htm text

uploading Website-Training\books\index.html to index.html text

uploading Website-Training\books\_vti_cnf to _vti_cnf directory created uploading Website-Training\books\_vti_cnf\index.htm to index.htm text uploading Website-Training\books\_vti_cnf\index.html to index.html text directory exited

directory exited

uploading Website-Training\calendar.html to calendar.html text

uploading Website-Training\contacts.html to contacts.html text

uploading Website-Training\estes-nov06.htm to estes-nov06.htm text

uploading Website-Training\formalbio.html to formalbio.html text

uploading Website-Training\fulloutline.html to fulloutline.html text

…часть строк опущена…

uploading Website-Training\_vti_pvt\writeto.cnf to writeto.cnf ?

uploading Website-Training\_vti_pvt\_vti_cnf to _vti_cnf directory created uploading Website-Training\_vti_pvt\_vti_cnf\_x_todo.htm to _x_todo.htm text uploading Website-Training\_vti_pvt\_vti_cnf\_x_todoh.htm

to _x_todoh.htm text directory exited

uploading Website-Training\_vti_pvt\_x_todo.htm to _x_todo.htm text uploading Website-Training\_vti_pvt\_x_todoh.htm to _x_todoh.htm text directory exited

Done: 366 files and 18 directories uploaded.

В текущей реализации сценарий в примере 13.15 обрабатывает только выгрузку деревьев каталогов — для тех, кто сопровождает веб-сайты на своем локальном компьютере и периодически выгружает изменения на сервер, рекурсивная выгрузка обычно имеет большую практическую ценность, чем рекурсивная загрузка. Чтобы также за гружать (создавать зеркальные копии) веб-сайты, содержащие вложенные подкаталоги, сценарий должен проанализировать вывод команды получения списка файлов в удаленном каталоге. По той же самой причине сценарий рекурсивной выгрузки не поддерживает очистку удаленного дерева каталогов — для реализации данной особенности также потребовалось бы организовать анализ списков удаленных файлов. Как это сделать, демонстрируется в следующем разделе.

Использованная литература:

Марк Лутц — Программирование на Python, 4-е издание, II том, 2011

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