Как скачать большой файл в Python через FTP (с мониторингом и переподключением)?
ОБНОВЛЕНИЕ № 1
Код в вопросе работает довольно хорошо для стабильного соединения (например, локальной сети или интранета).
ОБНОВЛЕНИЕ № 2
Я реализовал FTPClient
класс с ftplib, который может:
- контролировать ход загрузки
- переподключиться в случае таймаута или отключиться
- делает несколько попыток скачать файл
- показывает текущую скорость загрузки.
После повторного подключения он продолжает процесс загрузки с точки отключения (если это поддерживает FTP-сервер). Для подробностей смотрите мой ответ ниже.
Вопрос
Я должен реализовать задачу на python, которая ежедневно загружает кучу больших файлов (0,3-1,5 ГБ на файл * 200-300 файлов) через FTP, а затем выполняет некоторую обработку с файлами. Я сделал это через ftplib. Но время от времени он зависает и не может завершить загрузку некоторых файлов. Чтобы решить эту проблему, я начал играть с настройками KEEPALIVE, но я до сих пор не получил хороший результат
with closing(ftplib.FTP()) as ftp:
try:
ftp.connect(self.host, self.port, 30*60) #30 mins timeout
# print ftp.getwelcome()
ftp.login(self.login, self.passwd)
ftp.set_pasv(True)
ftp.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 75)
ftp.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
with open(local_filename, 'w+b') as f:
res = ftp.retrbinary('RETR %s' % orig_filename, f.write)
if not res.startswith('226 Transfer complete'):
logging.error('Downloaded of file {0} is not compile.'.format(orig_filename))
os.remove(local_filename)
return None
os.rename(local_filename, self.storage + filename + file_ext)
ftp.rename(orig_filename, orig_filename + '.copied')
return filename + file_ext
except:
logging.exception('Error during download from FTP')
подробности
- Обычно загрузка файла занимает 7-15 минут.
- FTP-сервер всегда показывает мне в журналах, что файлы полностью загружены, но клиентская часть зависает. Не каждый раз, а время от времени.
Вопросы
- Может ли это быть из-за отключения?
- Как реализовать монитор для процесса загрузки и повторно подключить его в случае, если он отключен
1 ответ
Поскольку я не мог найти хороших предложений или примеров кода, я реализовал свое собственное решение. Огромное спасибо сообществу Stackru за некоторые идеи, которые я использовал в своем коде. Я поместил код в GitHub ( pyFTPclient) из-за размера кода (~ 120 строк).
Я проверил решение в сети плохого качества (включая мобильный интернет 3G), и это было хорошо для меня. Но, конечно, это может иметь некоторые ошибки.
Буду признателен за любые комментарии или предложения. Заранее спасибо.