Descargar archivos grandes a través de FTP con python

Intento descargar diariamente un archivo de copia de seguridad de mi servidor a mi servidor de almacenamiento local, pero tengo algunos problemas.

Escribí este código (eliminé las partes inútiles, como la función de correo electrónico):

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() 

Y corro esto con un crontab como:

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

Funciona con archivos pequeños, pero con los archivos de copia de seguridad (aproximadamente 1.7Gb) se congela, el archivo descargado obtiene aproximadamente 1.2Gb y luego nunca crece (esperé aproximadamente un día), y el archivo de registro está vacío.

¿Alguna idea?

ps: estoy usando Python 2.6.5

Lo siento si respondo a mi propia pregunta, pero encontré la solución.

Intenté ftputil sin éxito, así que intenté de muchas maneras y, finalmente, esto funciona:

 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") [...] 

En mi archivo de registro encontré:

 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 

Lamentablemente, tengo que volver a conectarme a FTP incluso si el archivo se ha descargado completamente, en mi caso no es un problema, ya que también tengo que descargar el md5sum.

Como puede ver, no he podido detectar el tiempo de espera y volver a intentar la conexión, pero cuando lo hice, simplemente me reconecto de nuevo; Si alguien sabe cómo reconectarse sin crear una nueva instancia de ftplib.FTP, avíseme;)

Puede intentar establecer el tiempo de espera. De los documentos :

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

Implementé un código con ftplib que puede monitorear la conexión, la reconexión y el archivo de descarga en caso de falla. Detalles aquí: ¿Cómo descargar un archivo grande en python a través de ftp (con monitoreo y reconectar)?