- Создана пользователем Рудковский Михаил (доб. 1236). Последнее обновление: июл. 03, 2024 ( Дмитрий Гаврилов) Время чтения: 3 мин.
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.txtfrom 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.txtfrom 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")