Дерево страниц

resources/send_message_and_files/ftp.py

Модуль предоставляет высокоуровневый интерфейс для отправки файлов на ftp сервер в виде класса FTPClient.

При инициализации экземпляра класса (если параметр check_connection=True) - он пытается подключиться к ftp серверу и вызовет ошибку если подключиться не удалось.

Если при старте скрипта эта проверка прошла успешно - при работе скрипта ошибки не будут вызываться - скрипт будет автоматически пытаться переподключиться.

Класс одновременно держит активным только одно подключение. После отправки подключение закрывается.

Все файлы, которые отправляются методом FTPClient.send добавляются в очередь. После чего запускается worker отправки файлов из очереди в отдельном потоке.

Логика примерно такая:

  1. Берем первый файл из очереди
  2. Пытаемся его отправить
  3. Если во время отправки произошла ошибка ftplib.all_errors то файл возвращается в конец очереди а в callback передается status.ftp_error
  4. Если словили другую ошибку то файл в очередь не возвращается, а в callback возвращается status.error
  5. Если файл усешно отправлен - в callback передается status.success
  6. Возвращаемся к первому пункту

Атрибуты класса

  • host (str): Адрес ftp севрера.
  • port (int, optional): Порт ftp севрера, по умолчанию 21.
  • user (str, optional): Имя пользователя ftp. По умолчанию 'anonymous'.
  • passwd (str, optional): Пароль пользователя ftp. По умолчанию пустая строка.
  • work_dir (str, optional): Корневая папка на ftp сервера, куда будут отправляться все файлы. Если не указана все файлы отправляются в корневую директорию ftp.
  • callback (callable[str, str]): Callback функция, куда передается guid и статус задачи.
  • queue_maxlen (int, optional): Максимальная длина очереди на отправку. По умолчанию 1000.
  • check_connection (bool, optional): Если True - Проверяет подключение при инициализации. Вызывает CheckConnectionError если подключение не доступно. По умолчанию True.
  • passive_mode (bool, optional):Если True - Включает пассивный режим работы FTP. По умолчанию True.

Методы класса

  • check_connection() - Проверяет подключение к серверу. Вызывает CheckConnectionError если подключение не доступно.
  • send(file_path, remote_dir=None, callback=None, task_guid=None) - Зодает задачу для отправки на ftp сервер. Возвращает guid задачи.
    Аргументы метода:
    • file_path (str): Полный путь до файла, который необходимо отправить.
    • remote_dir (str, optional): Папка на удаленном сервере, куда необходимо сохранить файл. Если задан параметр work_dir то она также учитывается при отправке файла.
    • callback (callable[str, str]): Callback функция, куда передается guid и статус задачи. Если не задана - используется функция переданная в параметр callback класса.
    • task_guid (str)Guid задачи. По умолчанию задается с помощью функции host.random_guid()

Статусы отправки файла

Возможные статусы отправки файла содержатся в объекте status:

  • status.sending - Файл отправляется
  • status.error - Ошибка отправки файла
  • status.ftp_error - Ошибка соединения с ftp
  • status.success - Файл успешно отправлен
  • status.in_queue - Файл добавлен в очередь отправки

Примеры кода

Отслеживание статуса отправки файла

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

  • task_guid (str) - Guid задачи (возвращается также при вызове функции отправки)
  • state (str)- Текущий статус передачи файла
import os
import host
from ftp import FTPClient, status

tasks = {}


def callback(task_guid, state):
    popup = host.error
    if state == status.success or state == status.in_queue:
        popup = host.message
    elif state == status.sending:
        popup = host.alert
    popup("%s: %s" % (task_guid, state))
    
    if state == status.success:
        os.remove(tasks[task_guid])


client = FTPClient("localhost", port=21, user="trassir", passwd="12345", callback=callback)

file_to_send = "../file1.txt"
task_guid = client.send("../file1.txt")
tasks[task_guid] = file_to_send
Отправка файлов в разные директории

Если необходимо отправлять файлы в разные директории - НЕ НУЖНО СОЗДАВАТЬ РАЗНЫЕ ЭКЗЕМПЛЯРЫ КЛАССА. Классу можно задать глобальную директорию, в которой будет работать скрипт. А также отдельно директорию для каждого файла. Глобальная задается при инициализаци класса - аргумент work_dir При отправке файла метод FTPClient.send может принимать не обязательный аргумент remote_dir 

Отправка файлов в корень ftp

ftp
│ file1.txt
│ file2.txt

from ftp import FTPClient

client = FTPClient("localhost", port=21, user="trassir", passwd="12345")
client.send("../file1.txt")
client.send("../file2.txt")
Отправка всех файлов в директорию mypath
ftp
└───mypath
    │   file1.txt
    │   file2.txt
from ftp import FTPClient

client = FTPClient("localhost", port=21, user="trassir", passwd="12345", work_dir="mypath")
client.send("../file1.txt")
client.send("../file2.txt")
Отправка каждого файла в разные директории
ftp
└───file1_dir
│   │   file1.txt
│   
└───file2_dir
    └───subdir
        │   file2.txt
from ftp import FTPClient

client = FTPClient("localhost", port=21, user="trassir", passwd="12345")
client.send("../file1.txt", remote_dir="file1_dir")
client.send("../file2.txt", remote_dir="file2_dir/subdir")
Сложная иерархия папок

Используем папку script_path на ftp сервере и при этом внутри этой папки создаем другие папки для каждого файла

ftp
└───script_path
    └───file1_dir
    |   │ file1.txt
    └───file2_dir
        └───subdir
            | file2.txt

from ftp import FTPClient

client = FTPClient("localhost", port=21, user="trassir", passwd="12345", work_dir="script_path")


client.send("../file1.txt", remote_dir="file1_dir")
client.send("../file2.txt", remote_dir="file2_dir/subdir")