wiki:RussianDocumentation

Unfortunately, this translation is outdated. If you can, read the current documentation in English.

ftputil - высокоуровневая библиотека для клиента FTP протокола

Версия:2.1
Дата:2006-03-30
Резюме:высокоуровневая Python библиотека для клиента FTP протокола
Ключевые слова:FTP, замена ftplib, виртуальная файловая система
Автор:Stefan Schwarzer <sschwarzer@sschwarzer.net>
Русский перевод:
 Степанов Антон <antymail@mail.ru>

Введение

Модуль ftputil является высокоуровневым интерфейсом для ftplib модуля.Объекты FTPHost позволяют производить большое количество операций, аналогичных операциям в модулях os и os.path.

Примеры:
import ftputil

# download some files from the login directory
host = ftputil.FTPHost('ftp.domain.com', 'user', 'password')
names = host.listdir(host.curdir)
for name in names:
    if host.path.isfile(name):
        host.download(name, name, 'b')  # remote, local, binary mode

# make a new directory and copy a remote file into it
host.mkdir('newdir')
source = host.file('index.html', 'r')  # file-like object
target = host.file('newdir/index.html', 'w')  # file-like object
host.copyfileobj(source, target)  # similar to shutil.copyfileobj
source.close()
target.close()

Такие методы как FTPHost.lstat и FTPHost.stat позволяют узнать размер и время изменения файла. Последний может следовать по ссылкам аналогичным os.stat. Даже, такая функция как FTPHost.path.walk работает в этой библиотеке.

Дистрибутив содержит модуль UserTuple, который обеспечивает совместимость результатов модуля stat с версиями Python 2.0 и 2.1.

Иерархия исключений

Исключения находятся в пространстве имен пакета ftputil (например: ftputil.TemporaryError). Они организованы следующим образом

FTPError
    FTPOSError(FTPError, OSError)
        TemporaryError(FTPOSError)
        PermanentError(FTPOSError)
        ParserError(FTPOSError)
    FTPIOError(FTPError)
    InternalError(FTPError)
        RootDirError(InternalError)
        InaccessibleLoginDirError(InternalError)
    TimeShiftError(FTPError)

ниже приведено описание каждого исключения:

  • FTPError

    является корнем иерархии исключений модуля.

  • FTPOSError

    потомок OSError. Создан для подобия объектов модуля os и объектов модуля FTPHost. Сравните

    try:
        os.chdir('nonexisting_directory')
    except OSError:
        ...
    

    с

    host = ftputil.FTPHost('host', 'user', 'password')
    try:
        host.chdir('nonexisting_directory')
    except OSError:
        ...
    

    Представим функцию,

    def func(path, file):
        ...
    

    которая работает в локальной файловой системе и получает ошибки OSErrors. Если вы измените список параметров на

    def func(path, file, os=os):
        ...
    

    где параметр os означает os модуль, то вызывая функцию как

    host = ftputil.FTPHost('host', 'user', 'password')
    func(path, file, os=host)
    

    Вы сможете использовать тот же самый код как для локальной файловой системы так и для удаленной. Другое подобие между OSError и FTPOSError залючается в том, что последний возвращает FTP серверу код ошибки errno в свойстве объекта-исключения и текст ошибки strerror.

  • TemporaryError

    это исключение вызывается в том случае, если код ошибки полученной от FTP сервера находится в диапазоне от 400 до 499. Это исключение соответствует исключению ftplib.error_temp (хотя TemporaryError и ftplib.error_temp не являются идентичными).

  • PermanentError

    это исключение вызывается в том случае, если код ошибки полученной от FTP сервера находится в диапазоне от 500 до 599 (снова, это исключение подобно, но не идентично исключению ftplib.error_perm).

  • ParserError

    ошибка, которая возникает в течение анализа списка каталогов из сервера. Это исключение используется такими методами объекта FTPHost как: stat, lstat, и listdir.

  • FTPIOError

    это исключение обозначает ошибку ввода/вывода на удаленном компьютере. Эта ошибка, главным образом, связана с файл-подобными объектами которые были использованы при вызове функции FTPHost.file (FTPHost.open - псевдоним). Сравните:

    >>> try:
    ...     f = open('notthere')
    ... except IOError, obj:
    ...     print obj.errno
    ...     print obj.strerror
    ...
    2
    No such file or directory
    

    с

    >>> host = ftputil.FTPHost('host', 'user', 'password')
    >>> try:
    ...     f = host.open('notthere')
    ... except IOError, obj:
    ...     print obj.errno
    ...     print obj.strerror
    ...
    550
    550 notthere: No such file or directory.
    

    Как вы можете видеть, отрывки кода подобны. (Однако, коды ошибок не являются одинаковыми.)

  • InternalError

    относится к классу исключений которое вызывается из-за наличия ограничений FTP протокола или в следствие непосредственного выполнения модуля ftputil.

  • RootDirError

    при выполнении lstat - метода невозможно выполнить stat- запрос к корневому каталогу /. Если Вы знаете способ как это сделать, пожайлуста, сообщите мне. :-)

  • InaccessibleLoginDirError

    Это исключение вызывается только в том случае, если выполнятся одно из следующих условий:

    • Каталог, в который «Вы» помещаетесь при входе в систему не доступен, тогда запрос chdir будет прерван.
    • Ваш путь содержит одни пробелы.
  • TimeShiftError используется, чтобы обозначить ошибки, которые касаются метода time shift, например, попытка установить значение, которое не является кратным 1 часу

FTPHost - объекты

Конструкция

FTPHost запрос может быть произведен с использованием следующего вызова:

host = ftputil.FTPHost(host, user, password, account,
                       session_factory=ftplib.FTP)

Первые четыре параметра - строки с тем же самым значением, что и у FTP класса в ftplib модуле. Параметр session_factory may используется для того, чтобы произвести FTP подключение через другие фабрики, чем установленное по умолчанию значение ftplib.FTP. Например, M2Crypto распределение использует безопасный FTP класс, который получен из ftplib.FTP.

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

Эти функциональные возможности конструктора также позволяют "оборачивать" ftplib.FTP объекты, чтобы делать то, что невозможно сделать с использованием одного ftplib.FTP конструктора.

Например, предположите, что Вы хотите произвести соединение с другим портом, отличным от заданного по умолчанию, но ftplib.FTP предлагает это сделать только с использованием метода connect, но через другой конструктор. Решение состоит в создании "класса обертки":

import ftplib
import ftputil

EXAMPLE_PORT = 50001

class MySession(ftplib.FTP):
    def __init__(self, host, userid, password, port):
        """Act like ftplib.FTP's constructor but connect to other port."""
        ftplib.FTP.__init__(self)
        self.connect(host, port)
        self.login(userid, password)

# try not to use MySession() as factory, - use the class itself
host = ftputil.FTPHost(host, userid, password,
                       port=EXAMPLE_PORT, session_factory=MySession)
# use `host` as usual

При входе в систему, формат списка каталогов (необходимый для применения stat - методов к файлам и каталогам) определяется автоматически. Если нет, то Вы можете использовать метод set_directory_format , чтобы установить формат "вручную".

FTPHost - свойства и методы

Свойства

  • curdir, pardir, sep

    являются строками, которые обозначают текущий и родительский каталог на на отдаленном сервере. Sep опознает разделитель пути. Хотя RFC 959 (Протокол передачи файлов) обращает внимание на то, что эти значения могут зависеть от сервера. Unix машины , кажется, хорошо работают даже для не - Unix серверов.

Коррекция времени часового пояса

  • set_time_shift(time_shift)

    устанавливает так называемое значение сдвига времени (измеряемое в секундах). Сдвиг времени - различие между местным временем сервера и местным временем клиента в данный момент, т.е. по определению:

    time_shift = server_time - client_time
    

    Установка этого значения важна, если upload_if_newer и download_if_newer работали правильно, даже если часовой пояс FTP сервера отличается от часового пояса клиента (где библиотека ftputil запущена). Обратите внимание на то, что значение сдвига времени может быть отрицательным.

    Если значение сдвига времени является неправльным, например не является кратным 1 часу, или абсолютное зачение больше чем 24 часа, то вызывется исключение: TimeShiftError.

    См. также synchronize_times как простой способ установки сдвига времени.

  • time_shift()

    возвращает установленное текущее значение сдвига времени. См. set_time_shift (выше) для его определения.

  • synchronize_times()

    синхронизирует локальное время сервера и клиента, так, чтобы методы upload_if_newer и download_if_newer правильно работали, даже если клиент и сервер находятся в различных часовых поясах. Для того, чтобы все это работало должны выполняться следующие условия:

    • Должно быть установлено подключение между сервером и клиентом.
    • Клиент должен иметь доступ к каталогу, который является текущим, когда synchronize_times вызывается.
    • Каталог, к которому обращаются не должен быть корневым каталогом (т.е. /) FTP сервера.

    Если Вы не можете выполнить эти условия, Вы можете установить значение сдвига времени вручную с использованием set_time_shift. Попытка вызова synchronize_times, если вышеупомянутые условия не выполняются приведет к генерации TimeShiftError исключения.

Файлы и каталоги

  • file(path, mode='r')

    возвращает файл-подобный объект, который связан с путем на отдаленном главном компьютере. Этот путь может быть абсолютным, или относительным для текущего каталога на отдаленном главном компьютере (этот каталог может быть определен с помощью getcwd метода). Также как и для локальных файлов задается по умолчанию режим - "r", т. е. чтение текстовых файлов. Допустимые режимы - "r", "rb", "w", и "wb".

  • open(path, mode='r')

    является псевдонимом для file (см. выше).

  • copyfileobj(source, target, length=64*1024)

    копирует содержимое из файл-подобного объекта-источника в файл-подобный объект-адресат. Единственное различие с shutil.copyfileobj - есть заданный по умолчанию размер буфера.

  • close()

    закрывает соединение с отдаленным компьютером. После этого, взаимодействие с FTP сервером невозможно без создания нового объекта FTPHost.

  • getcwd()

    возвращает абсолютный путь текущего каталога на отдаленном компьютере. Этот метод действует подобно методу os.getcwd.

  • chdir(directory)

    устанавливает текущий каталог на FTP сервере. Это метод похож на метод os.chdir, а Вы что ожидали.:-)

  • mkdir(path, [mode])

    создаёт каталог на отдаленном компьютере. При своём выполнении, не создает "промежуточные" каталоги, которые уже существуют. При этом параметр mode игнорируется. Создан для совместимости с os.mkdir,если объект FTPHost вставляется в функцию вместо os модуля (см. подраздел исключений Питона выше).

  • makedirs(path, [mode]) работает аналогично команде mkdir (см. выше, но, также, создаёт "промежуточные" каталоги (также как и команда os.makedirs). Параметр mode введен только для совместимости с командой os.makedirs и в данном случае игнорируется.

  • rmdir(path)

    удаляет заданный удаленный каталог.

    В предыдущих версиях ftputil, эта функция зависела от отдаленного сервера, были эти каталоги пустыми или нет. ftputil версии 2.0 по умолчанию позволяет удалять только пустые каталоги.

    Если Вы хотите установить ftputil 2.0, но при этом произвести минимальные изменения в исходном тексте, добавьте дполнительный параметр _remove_only_empty=False. Обратите внимание, что это метод осуждается и, вероятно, не будет поддерживаться в следующих версиях ftputil.

  • remove(path)

    удаляет файл на отдаленном компьютере (подобен методу os.remove).

  • unlink(path)

    является псевдонимом для remove.

  • rename(source, target)

    переименовывает исходный файл (или каталог) на FTP сервере.

  • listdir(path)

    возвращает список, содержащий имена файлов и каталогов по заданном пути; подобен методу os.listdir.

  • walk(top, topdown=True, onerror=None)

    команда обхода дерева каталогов, аналогична команде os.walk в версии Python 2.3. Фактически, FTPHost.walk использует код из Python системы с введением необходимых модификаций, см. документацию по языку.

    Если остальные команды библиотеки ftputil могут работать с любой версией Python, то начиная с версии 2.0 и выше, метод walk требует наличие генераторов и будет работать с версией Python 2.2 и выше.

Отправка и загрузка файлов

  • upload(source, target, mode='')

    копирует локальный файл (с заданным именем, например, в виде строки) на отдаленный компьютер по соответствующему адресу. Как источник, так и адресат могут иметь абсолютные или относительные пути текущего каталога (на локальном или отдаленного компьютере, соответственно). Режим отправки может быть " " или "@" для ASCII, или "b" для двоичного кода. Режим ASCII задан по умолчанию.

  • download(source, target, mode='')

    выполняет загрузку из удаленного источника в конечный файл. И источник и адресат являются параметрами задаваемыми в виде строки. Дополнительное описание применения метода загрузки см. ниже

  • upload_if_newer(source, target, mode='')

    подобен методу копирования. Единственное отличие - то, что файл отправляется, если время последней модификации для исходного файла более современное чем конечного файла, или адресат не существует вообще. Если отправка фактически происходит, то возвращается истинное значение, иначе - ложь.

    Обратите внимание, что этот метод только проверяет существование и/или время модификации источника и конечного файла; что не может привести замене в режиме передачи, например:

    # transfer in ASCII mode
    host.upload_if_newer('source_file', 'target_file', 'a')
    # won't transfer the file again
    host.upload_if_newer('source_file', 'target_file', 'b')
    

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

    • используйте upload вместо upload_if_newer, или
    • удалите конечный файл используя FTPHost.remove, затем используте upload или upload_if_newer, чтобы передать файл снова.

    Если кажется, что файл отправлен "напрасно", то читайте подраздел настройки time shift.

  • download_if_newer(source, target, mode='')

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

    Если кажется, что файл отправлен напрасно, то читайте подраздел настройки time shift.

Stat - методы для файлов и каталогов

Методы lstat и stat (и другие) основываются на формате каталога, используемого FTP сервером. При соединении с компьютером, конструктор FTPHost выбирает формат, который, как он считает, является правильным. Однако, если Вы получите странные результаты (или исключения), следует установить формат каталога "вручную". Установка форамата произойдет незамедлительно после вызова функции:

  • set_directory_format(server_format)

    server_format - представляет собой строку "unix", либо - "ms". Чтобы

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

    Если результирующие строки имеют вид:

    drwxr-sr-x   2 45854    200           512 Jul 30 17:14 image
    -rw-r--r--   1 45854    200          4604 Jan 19 23:11 index.html
    

    используйте строку "unix" как аргумент.

    Если вывод имеет вид таких строк:

    12-07-01  02:05PM       <DIR>          XPLaunch
    07-17-00  02:08PM             12266720 digidash.exe
    

    тогда используте "ms" для установки значения server_format.

    Если ни один из вышеупомянутых параметров настройки не поможет, тогда свяжитесь со мной. Был бы очень хорошо, если Вы смогли бы выслать листинг ошибочного вывода (вывод с использованием команды DIR).

Если, при запросе, lstat или stat методы выдают неправильное время изменения файла, или неправильно выдают дату, используйте методы, которые работают с учётом разницы во времени (time shift).

  • lstat(path)

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

    • Результат получается вследствие анализа вывода команды DIR на сервере. Поэтому, результат команды FTPHost.lstat не может содержать больше информации чем полученный текст. В особенности:
    • Пользователь и группа пользователей могут быть определены толоко через строки, но не как числа, и только сервер выдает эти строки. Это Это обычно относится к самим Unix серверами, но никак не относится к FTP программам сервера.
    • Значения времени последней модификации файла могут быть неточными, все зависит от информации полученной от сервера. Если файл был изменен раньше чем год назад , то точность значения времени изменения файла не будет больше одного дня. Для более новых файлов, точность времени модификации файла может быть равной одной минуте.
    • Ссылки могут быть явными только на тех серверах, которые получают информацию из вывода команды DIR.
    • Пункты, которые не могут быть определены принимают значение None.
    • Также существует проблема с применением stat - метода к корневому каталогу. В этом случае вызывается ошибка RootDirError. Проблема имеет отношение к алгоритму, используемому в методе (l)stat, и я не знаю ни одного способа, который помог бы её решить.
В настоящее время, библиотека ftputil поддерживает формат MS Robin FTP сервера. Формат который в основном используется Unix серверами также поддерживается. Если Вы нуждаетесь в поддержке других форматов, пожалуйста, свяжитесь со мной по электронной почте. Адрес приведён в конце этого текста.
  • stat(path) возвращает stat информацию для файлов, которые указаны по ссылке. Этот метод следует по множеству ссылок, пока регулярный файл или каталог не будут найдены. Если цепочка ссылок зациклена то вызывается исключение: PermanentError.

FTPHost.path

FTPHost объекты имеют такое свойство как: path, подобное os.path. Приведенные ниже методы могут прменяться к отдаленному компьютеру с семантикой кода аналогичной семантике кода методов os.path:

abspath(path)
basename(path)
commonprefix(path_list)
dirname(path)
exists(path)
getmtime(path)
getsize(path)
isabs(path)
isdir(path)
isfile(path)
islink(path)
join(path1, path2, ...)
normcase(path)
normpath(path)
split(path)
splitdrive(path)
splitext(path)
walk(path, func, arg)

FTPFile - объекты

FTPFile объекты создаются при вызове конструкций FTPHost.file (или FTPHost.open) и имеют аналогичные методы, (с теми же параметрами, и с той же семантикой) что и методы, работающие с локальными файлами:

close()
read([count])
readline([count])
readlines()
write(data)
writelines(string_sequence)
xreadlines()

и атрибут closed. Для получения детальной информации смотрите раздел File objects в справочнике по библиотеке.

Обратите внимание на то, что ftputil поддерживает и двоичный и текстовый режимы работы со строкой завершающей преобразования.

Советы и подсказки / FAQ

Где я могу получить самую последнюю версию?

Смотрите http://www.sschwarzer.net/python/python_software.html#ftputil. Объявления относительно новых версий будут рассылаться списку адресатов (см. вопрос ниже). Объявления относительно появления главных модификаций отправляются в службу новостей comp.lang.python .

Имеется ли почтовый ящик на ftputil?

Да, вы можете подписаться на http://codespeak.net/mailman/listinfo/ftputil или прочитать архивы на http://codespeak.net/pipermail/ftputil/.

Я нашел ошибку! Что теперь?

Перед сообщением об ошибке, удостоверьтесь в том, что Вы пользовались самой последней версией ftputil. Эта ошибка уже могла быть устранена.

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

В сообщении об ошибке, пожалуйста, введите следующую информацию:

  • версия ftputil
  • версия Python
  • тип и версия FTP сервера (отображается в "сообщении приветствия")
  • операционные системы и их версии на сервере и клиенте (выводятся при вводе командной строки uname -a на Unix)
  • описание ошибки
  • если возможно, то краткий пример кода, который приводит к ошибке
  • если возможно, то идеи, которые бы помогли найти причину ошибки

Соединение по другому порту

По умолчанию, FTPHost объект соединяется по обычному FTP порту. Если Вы хотите использовать другой порт, то просмотрите раздел FTPHost construction.

Вы можете использовать тот же самый подход как при подключении в активном режиме, так и при подключении в пассивном режиме, как Вам нравится.

Использование активных или пассивных подключений

Используйте оберточный класс для ftplib.FTP, как описано в разделе FTPHost construction:

import ftplib

class ActiveFTPSession(ftplib.FTP):
    def __init__(self, host, userid, password):
        """
        Act like ftplib.FTP's constructor but use active mode
        explicitly.
        """
        ftplib.FTP.__init__(self)
        self.connect(host, port)
        self.login(userid, password)
        # see http://docs.python.org/lib/ftp-objects.html
        self.set_pasv(False)

Используйте этот класс как аргумент``session_factory`` в конструкторе``FTPHost``.

Условная отправка/загрузка с/на сервер(а) в различных часовых поясах

Вы можете заметить, что ftputil отправляет или загружает лишние файлы, когда это не требуется. Это может случаться тогда, когда FTP сервер и клиент, на котором запущена библиотека ftputil, находятся в различных часовых поясах. Смотрите раздел по установке time shift. Может быть, достаточно вызвать метод synchronize_times.

Файл - связанные методы-запросы (например: listdir) возвращают неожиданные результаты

Если, например, listdir или lstat возвращают неправильное значение или вызывают исключение, то это может происходить из-за неправильно определенного формата каталога. См. set_directory_format.

Я не нахожу ответ на мою проблему в этом документе

Пожалуйста, вышлите мне на электронный почтовый ящик Ваш вопрос, и я посмотрю, что смогу для Вас сделать. :-) Вероятно лучший способ заключается в том, чтобы выслать ваш вопрос по адресу ftputil@codespeak.net; потенциально, гораздо большее число людей сможет помочь Вам.

Ошибки и ограничения

  • ftputil нуждается в версии Python 2.0 или выше.
  • При выполнении lstat метода возвращается неправильное значение для корневого каталога /. Если Вы знаете как решить эту проблему, пожалуйста, сообщите мне. Корневой каталог может использоваться в таких методах, соответственно: FTPHost.path.exists/isfile/isdir/islink, хотя...
  • Блокировка времени исполнения индивидуальных дочерних процессов. Эта проблема возникает в том случае, если FTPHost объект, или генерированные FTPFile объекты не используются в течение 10 минут и более.
  • До сих пор, я не обращал внимание на безопасность потока. В принципе, по крайней мере, различные FTPFile объекты должны работать в различных потоках.
  • FTPFile объекты в текстовом режиме не поддерживают символы размером больше одного байта. Пожалуйста, отправьте мне письмо, если вы работатете с мультибайтовыми потоками текста в ваших FTP сеансах.
  • В данной версии невозможно прервать процесс отправки и загрузки файлов. Свяжитесь со мной, если у Вас возникли с этим проблемы.
  • UserTuple класс в модуле UserTuple.py, пока полностью не проверен. Если у вас возникла проблема при работе с этим классом, сообщите мне.

Файлы

Если не изменены опции инсталляции, то ftputil файлы будут размещены в ftputil` пакете. Документация (в reStructured Text и в формате HTML ) находится в той же самой директории.

Файлы _test_*.py и _mock_ftplib.py служат для тестирования модуля. Если Вы используете библиотеку ftputil (т.е. не модифицируете её), Вы можете удалить эти файлы.

Справочники

Автор

Библиотека ftputil написана Стефаном Шварцером (Stefan Schwarzer) <sschwarzer@sschwarzer.net>.

Обратная связь учтена. :-)

Last modified 11 years ago Last modified on Feb 1, 2010, 12:56:47 PM