- Создал(а) Рудковский Михаил (доб. 1236), редактировал(а) Дмитрий Гаврилов июл 03, 2024
resources/send_message_and_files/ftp.py
Модуль предоставляет высокоуровневый интерфейс для отправки файлов на ftp сервер в виде класса FTPClient
.
При инициализации экземпляра класса (если параметр check_connection=True
) - он пытается подключиться к ftp серверу и вызовет ошибку если подключиться не удалось.
Если при старте скрипта эта проверка прошла успешно - при работе скрипта ошибки не будут вызываться - скрипт будет автоматически пытаться переподключиться.
Класс одновременно держит активным только одно подключение. После отправки подключение закрывается.
Все файлы, которые отправляются методом FTPClient.send
добавляются в очередь. После чего запускается worker отправки файлов из очереди в отдельном потоке.
Логика примерно такая:
- Берем первый файл из очереди
- Пытаемся его отправить
- Если во время отправки произошла ошибка
ftplib.all_errors
то файл возвращается в конец очереди а вcallback
передаетсяstatus.ftp_error
- Если словили другую ошибку то файл в очередь не возвращается, а в
callback
возвращаетсяstatus.error
- Если файл усешно отправлен - в
callback
передаетсяstatus.success
- Возвращаемся к первому пункту
Атрибуты класса
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")