Удаление деревьев каталогов на сервере

udalenie derevev katalogov na servere Сценарии на стороне клиента

И последний пример многократного использования программного кода: когда я приступил к тестированию сценария uploadall из предыдущего раздела, он содержал ошибку, которая вызывала бесконечный рекурсивный цикл, снова и снова копируя весь сайт в новые подкаталоги, пока FTP-сервер не закрывал соединение (непредусмотренная особенность программы!). Фактически выгрузка продолжалась до достижения 13 уровня вложенности, прежде чем сервер закрывал соединение — это приводило к блокированию моего сайта, заставляя исправить ошибку.

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

Пример 13.16. PP4E\Internet\Ftp\Mirror\cleanall.py

#!/bin/env python

############################################################################ расширяет класс FtpTools возможностью удаления файлов и подкаталогов

в дереве каталогов на сервере; поддерживает удаление вложенных подкаталогов; зависит от формата вывода команды dir(), который может отличаться

на некоторых серверах! — смотрите подсказки в файле

Tools\Scripts\ftpmirror.py, в каталоге установки Python;

добавьте возможность загрузки дерева каталогов с сервера;

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

from ftptools import FtpTools

class CleanAll(FtpTools):

"""

удаляет все дерево каталогов на сервере def __init__(self):

self.fcount = self.dcount = 0

def getlocaldir(self):

return None # не имеет смысла здесь

def getcleanall(self)

подпись: return true# само собой разумеется здесь

def cleanDir(self)

для каждого элемента в текущем каталоге на сервере

удаляет простые файлы, выполняет рекурсивный спуск и удаляет подкаталоги, метод dir() объекта FTP передает каждую строку указанной функции или методу



self.connection.delete(fname) self.fcount += 1

подпись: else:
print('directory', fname) self.connection.cwd(fname) self.cleandir()
self.connection.cwd('..') self.connection.rmd(fname)
self.dcount += 1 print('directory exited')
подпись: # каталог: удалить рекурсивно
# переход в каталог на сервере
# очистить подкаталог
# возврат на уровень выше
# удалить пустой каталог
# на сервере



 


if __name__ == ‘__main__’:

ftp = CleanAll()

ftp.configTransfer(site=’learning-python.com’, rdir=’training’, user=’lutz’)

ftp.run(cleanTarget=ftp.cleanDir)

print(‘Done:’, ftp.fcount, ‘files and’, ftp.dcount, ‘directories cleaned.’)

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

C:\\PP4E\Internet\Ftp> ftp learning-python.com ftp> cd training ftp> dir

drwxr-xr-x 11 5693094 450 4096 May 4 11:06 .

drwxr-x 19 5693094 450 8192 May 4 10:59 ..

-rwr

1 5693094

450

15825

May 4 11:02 2009-public-classes.htm

-rwr

1 5693094

450

18084

May 4 11:02 2010-public-classes.html

drwxr-x

3 5693094

450

4096

May 4 11:02 books

-rwr

1 5693094

450

3783

May 4 11:02 calendar-save-aug09.html

-rwr

1 5693094

450

3923

May 4 11:02 calendar.html

drwxr-x

2 5693094

450

4096

May 4 11:02 images

-rwr

1 5693094

450

6143

May 4 11:02 index.html

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

 

Формат вывода этого метода потенциально зависит от конкретного сервера, поэтому проверьте формат вывода на своем сервере, прежде чем приступать к использованию этого сценария. Для данного сервера провайдера, работающего под управлением Unix, если первый символ первого элемента строки является символом «d», это означает, что имя файла в конце строки является именем каталога. Анализ строки заключается в простом ее разбиении по пробельным символам и извлечении составляющих ее частей.

Обратите внимание, что этот сценарий, как и предшествующие ему, должен пропускать символические обозначения «.» и «..» текущего и родительского каталогов для корректной работы с данным сервером. Это может показаться странным, но появление этих имен в выводе также может зависеть от сервера — некоторые серверы, которые я использовал при опробовании примеров для этой книги, не включали эти специальные имена в списки. Мы можем проверить особенности сервера в этом отношении, используя ftplib в интерактивном сеансе, как если бы это был переносимый клиент FTP:

C:\\PP4E\Internet\Ftp> python

>  >> from ftplib import FTP

>  >> f = FTP(‘ftp.rmi.net’)

>  >> f.login(‘lutz’, ‘xxxxxxxx’) # вывод строк опущен

>  >> for x in f.nlst()[:3]: print(x) # в списках отсутствуют имена . и ..

2004-longmont-classes.html

2005-longmont-classes.html

2006-longmont-classes.html

>  >> L = []

>  >> f.dir(L.append) # тот же список, но с подробной информацией

>  >> for x in L[:3]: print(x)

>  rw-rr 1 ftp ftp 8173 Mar 19 2006 2004-longmont-classes.html

>  rw-rr 1 ftp ftp 9739 Mar 19 2006 2005-longmont-classes.html

>  rw-rr 1 ftp ftp 805 Jul 8 2006 2006-longmont-classes.html

С другой стороны, сервер, который я использовал в этом разделе, включал специальные имена, состоящие из точек. Для надежности сценарий должен пропускать эти имена в списке, возвращаемом удаленным сервером, на случай, если он будет взаимодействовать с сервером, включающем их в список (здесь эта проверка обязательна, чтобы избежать попадания в бесконечный рекурсивный цикл!). Подобную осторожность не требуется проявлять при работе со списками содержимого локальных каталогов, потому что функция os.listdir никогда не включает имена «.» и «..» в свои результаты, но положение вещей на «Диком Западе», каким сейчас является Интернет, не является таким же согласованным:

>>> f = FTP(‘learning-python.com’)

>>> f.login(‘lutz’, ‘xxxxxxxx’) # вывод строк опущен

>   >> for x in f.nlst()[:5]: print(x) # включает имена . и .. здесь

.hcc.thumbs

2009-public-classes.htm

2010-public-classes.html

>   >> L = []

>   >> f.dir(L.append) # тот же список, но с подробной информацией

>   >> for x in L[:5]: print(x)

drwxr-x

19 5693094

450

8192

May

4 10:59 .

drwxr-x

19 5693094

450

8192

May

4 10:59 ..

drwx

2 5693094

450

4096

Feb

18 05:38 .hcc.thumbs

-rwr

1 5693094

450

15824

May

1 14:39 2009-public-classes.htm

-rwr

1 5693094

450

18083

May

4 09:05 2010-public-classes.html

 

Ниже приводится вывод сценария cleanall — он появляется в окне консоли в процессе работы сценария. Добиться того же эффекта можно с помощью команды rm -rf Unix, выполнив ее в окне сеанса SSH или Telnet, но сценарий Python выполняется на стороне клиента и не требует наличия возможности удаленного доступа, кроме поддержки протокола FTP на стороне клиента:

C:\PP4E\Internet\Ftp\Mirror> cleanall.py

Password for lutz on learning-python.com: connecting

file 2009-public-classes.htm

file 2010-public-classes.html

file Learning-Python-interview.doc

file Python-registration-form-010.pdf

file PythonPoweredSmall.gif

directory _derived

file 2009-public-classes.htm_cmp_DeepBlue100_vbtn.gif

file 2009-public-classes.htm_cmp_DeepBlue100_vbtn_p.gif

file 2010-public-classes.html_cmp_DeepBlue100_vbtn_p.gif

file 2010-public-classes.html_cmp_deepblue100_vbtn.gif directory _vti_cnf

file 2009-public-classes.htm_cmp_DeepBlue100_vbtn.gif

file 2009-public-classes.htm_cmp_DeepBlue100_vbtn_p.gif

file 2010-public-classes.html_cmp_DeepBlue100_vbtn_p.gif

file 2010-public-classes.html_cmp_deepblue100_vbtn.gif directory exited directory exited

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

file priorclients.html

file public_classes.htm

file python_conf_ora.gif file topics.html

Done: 366 files and 18 directories cleaned.

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

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

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