Скачать большие файлы через FTP с Python - PullRequest
7 голосов
/ 30 ноября 2011

Я пытаюсь ежедневно загружать файл резервной копии со своего сервера на локальный сервер хранения, но у меня возникают некоторые проблемы.

Я написал этот код (удалил ненужные части, как функцию электронной почты):

import os
from time import strftime
from ftplib import FTP
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders

day = strftime("%d")
today = strftime("%d-%m-%Y")

link = FTP(ftphost)
link.login(passwd = ftp_pass, user = ftp_user)
link.cwd(file_path)
link.retrbinary('RETR ' + file_name, open('/var/backups/backup-%s.tgz' % today, 'wb').write)
link.delete(file_name) #delete the file from online server
link.close()
mail(user_mail, "Download database %s" % today, "Database sucessfully downloaded: %s" % file_name)
exit()

И я запускаю это с помощью crontab, например:

40    23    *    *    *    python /usr/bin/backup-transfer.py >> /var/log/backup-transfer.log 2>&1

Он работает с небольшими файлами, но с файлами резервных копий (около 1.7Gb) он зависает, загруженный файл получает около 1.2Затем Gb никогда не растет (я ждал около дня), и файл журнала пуст.

Есть идеи?

ps: я использую Python 2.6.5

Ответы [ 3 ]

10 голосов
/ 02 декабря 2011

Извините, если я отвечу на свой вопрос, но я нашел решение.

Я пробовал ftputil безуспешно, поэтому я пробовал много способов, и, наконец, это работает:

def ftp_connect(path):
    link = FTP(host = 'example.com', timeout = 5) #Keep low timeout
    link.login(passwd = 'ftppass', user = 'ftpuser')
    debug("%s - Connected to FTP" % strftime("%d-%m-%Y %H.%M"))
    link.cwd(path)
    return link

downloaded = open('/local/path/to/file.tgz', 'wb')

def debug(txt):
    print txt

link = ftp_connect(path)
file_size = link.size(filename)

max_attempts = 5 #I dont want death loops.

while file_size != downloaded.tell():
    try:
        debug("%s while > try, run retrbinary\n" % strftime("%d-%m-%Y %H.%M"))
        if downloaded.tell() != 0:
            link.retrbinary('RETR ' + filename, downloaded.write, downloaded.tell())
        else:
            link.retrbinary('RETR ' + filename, downloaded.write)
    except Exception as myerror:
        if max_attempts != 0:
            debug("%s while > except, something going wrong: %s\n \tfile lenght is: %i > %i\n" %
                (strftime("%d-%m-%Y %H.%M"), myerror, file_size, downloaded.tell())
            )
            link = ftp_connect(path)
            max_attempts -= 1
        else:
            break
debug("Done with file, attempt to download m5dsum")
[...]

В моем лог-файле я нашел:

01-12-2011 23.30 - Connected to FTP
01-12-2011 23.30 while > try, run retrbinary
02-12-2011 00.31 while > except, something going wrong: timed out
    file lenght is: 1754695793 > 1754695793
02-12-2011 00.31 - Connected to FTP
Done with file, attempt to download m5dsum

К сожалению, мне нужно повторно подключиться к FTP, даже если файл был полностью загружен, что в моем cas не является проблемой, потому что мне также нужно скачать md5sum.

Как вы можете видеть, я не смог обнаружить тайм-аут и повторить соединение, но когда я получил тайм-аут, я просто переподключился снова; Если кто-то знает, как восстановить соединение без создания нового экземпляра ftplib.FTP, дайте мне знать;)

2 голосов
/ 01 октября 2014

Я реализовал код с ftplib, который может контролировать соединение, переподключать и перезагружать файл в случае сбоя.Подробности здесь: Как скачать большой файл в python через ftp (с мониторингом и переподключением)?

2 голосов
/ 30 ноября 2011

Вы можете попытаться установить время ожидания. Из документов :

# timeout in seconds
link = FTP(host=ftp_host, user=ftp_user, passwd=ftp_pass, acct='', timeout=3600)
...