Задача
Мониторить FTP и загружать с него появляющиеся там файлы. Файлы лежат в различных папках, имеющих подпапку AIR, в которой и находятся интересующие нас файлы.
Решение по идеальной модели
Ниже представлен реальный код, который использовался для решения поставленной задачи. Основой алгоритма было решение -- мы будем каждые пять минут просматривать папки на FTP и забирать все файлы, время создания которых отстоит от текущего не более чем на 5 минут
import pysftp
import sys
import os
import time
#sftp connection information cinfo = {'host':'host.ru', username':'user', 'password':'password'}
#folder with tickets local_dir = '\\\\cname\\files\\appdata\\source'
#get local time local_time = time.time()
#change the current folder to the folder with tickets os.chdir(local_dir)
#connect to sftp sftp = pysftp.Connection(**cinfo)
#get list folders list_folders = sftp.listdir()
for folder in list_folders:
#get a list of files attributes list_files = sftp.listdir_attr(folder + '/AIR')
for file in list_files:
#Download file if it was created less than 5 minutes ago. if local_time - file.st_mtime < 300: sftp.get(remotepath=folder + '/AIR/' + file.filename, preserve_mtime=True)
#close sftp connection sftp.close()
Ошибки идеальной модели
Приведенная программа содержит типичную ошибку идеальной модели, поскольку создатель рассчитывал, что
- сервер FTP доступен в любое время.
- все папки на сервере содержат папку AIR
- она будет вызываться точно каждые 5 минут
- если на сервере есть подходящий файл, то его можно скачать
Все четыре предположения не верны. Сервер может не работать или не быть доступен из-за проблем с сетью. Даже если есть договоренность о структуре каталогов, нет гарантии, что кто-то не создаст папку, не содержащую AIR. Обычные операционные системы не выдерживают интервалы абсолютно точно. Файл, который вы собираетесь скачивать, может быть занят другой программой. Не явно в 3 содержится и предположение, что мы заберем все файлы созданные в интервале (сейчас - 5 минут). А это не так. Любой сбой нарушающий предположения 1-4 приведет, к тому, что будет пропущена часть или все файлы из указанного интервала.
Как исправить
Основная проблема кроется в схеме отбора файлов. Использование непересекающихся интервалов плохая идея. Если вы пропустили файл, при таком подходе у вашей программы уже не будет еще одной попытки. Расширив интервал до часа, при пятиминутном интервале запуска можно получить более десятка попыток. Другой фактор, влияющий на величину разрешенного интервала -- как долго программа может вообще не запускаться. Если ваш сервер остановлен на 4 часа, то с часовым интервалом вы не загрузите файлы за 3 часа с начала простоя.
При использование пересекающихся интервалов возникает задача отслеживания загруженных файлов. Но ее не сложно решить, записывая имена загруженных файлов в файл или базу данных. Желательно в таком случае удалять старые записи, выходящие за разрешенный интервал. Я видел файл лога размером в 4ГБ.
Расширение разрешенного интервала решит проблемы 1 и 3, но может споткнуться на второй и четвертой., если из раза в раз файл окажется не доступным или папка AIR будет отсутствовать в папке из начала списка. Эта проблема разрешается обработкой исключения внутри цикла по папкам и по файлам, чтобы пропустить сбойный элемент и обработать остальные. Это типичный случай. Всегда, когда у вас есть для обработки несколько объектов, заключайте обработку объекта в обработчик исключений.
Логи
У создателя программы было еще одно идеальное предположение, что его творение будет работать идеально и никогда не потребуется расследовать, что же пошло не так и мы не досчитались файлов. Поэтому в ней не используются логи. Для производственной программы это критический недостаток Логи должны быть всегда и давать вам возможность восстановить картину произошедшего.