2009-07-09 5 views
2

Je dois télécharger certains fichiers à partir d'un serveur FTP. Cela semble assez prosaïque. Cependant, la façon dont ce serveur se comporte est que si le fichier est très volumineux, la connexion se bloque lorsque le téléchargement se termine.Python dire quand un transfert ftp se termine à la fin

Comment puis-je gérer cela gracieusement en utilisant ftplib en python?

code python Exemple:

from ftplib import FTP 

... 

ftp = FTP(host) 
ftp.login(login, passwd) 
files=ftp.nlst() 
ftp.set_debuglevel(2) 

for fname in files: 
    ret_status = ftp.retrbinary('RETR ' + fname, open(fname, 'wb').write) 

sortie de débogage de ce qui précède:

*cmd* 'TYPE I' 
*put* 'TYPE I\r\n' 
*get* '200 Type set to I.\r\n' 
*resp* '200 Type set to I.' 
*cmd* 'PASV' 
*put* 'PASV\r\n' 
*get* '227 Entering Passive Mode (0,0,0,0,10,52).\r\n' 
*resp* '227 Entering Passive Mode (0,0,0,0,10,52).' 
*cmd* 'RETR some_file' 
*put* 'RETR some_file\r\n' 
*get* '125 Data connection already open; Transfer starting.\r\n' 
*resp* '125 Data connection already open; Transfer starting.' 
[just sits there indefinitely] 

C'est ce que ça ressemble quand je tente le même télécharger en utilisant -v boucle:

* About to connect() to some_server port 21 (#0) 
* Trying some_ip... connected 
* Connected to some_server (some_ip) port 21 (#0) 
< 220 Microsoft FTP Service 
> USER some_user 
< 331 Password required for some_user. 
> PASS some_password 
< 230 User some_user logged in. 
> PWD 
< 257 "/some_dir" is current directory. 
* Entry path is '/some_dir' 
> EPSV 
* Connect data stream passively 
< 500 'EPSV': command not understood 
* disabling EPSV usage 
> PASV 
< 227 Entering Passive Mode (0,0,0,0,11,116). 
* Trying some_ip... connected 
* Connecting to some_ip (some_ip) port 2932 
> TYPE I 
< 200 Type set to I. 
> SIZE some_file 
< 213 229376897 
> RETR some_file 
< 125 Data connection already open; Transfer starting. 
* Maxdownload = -1 
* Getting file with size: 229376897 
{ [data not shown] 
    % Total % Received % Xferd Average Speed Time Time  Time Current 
           Dload Upload Total Spent Left Speed 
100 218M 100 218M 0  0 182k  0 0:20:28 0:20:28 --:--:--  0* FTP response timeout 
* control connection looks dead 
100 218M 100 218M 0  0 182k  0 0:20:29 0:20:29 --:--:--  0* Connection #0 to host some_server left intact 

curl: (28) FTP response timeout 
* Closing connection #0 

La sortie de wget est aussi intéressante, elle remarque que la connexion est morte, puis tente de télécharger de nouveau le fi le qui confirme seulement qu'il est déjà terminé:

--2009-07-09 11:32:23-- ftp://some_server/some_file 
      => `some_file' 
Resolving some_server... 0.0.0.0 
Connecting to some_server|0.0.0.0|:21... connected. 
Logging in as some_user ... Logged in! 
==> SYST ... done. ==> PWD ... done. 
==> TYPE I ... done. ==> CWD not needed. 
==> SIZE some_file ... 229376897 
==> PASV ... done. ==> RETR some_file ... done. 
Length: 229376897 (219M) 

100%[==========================================================>] 229,376,897 387K/s in 18m 54s 

2009-07-09 11:51:17 (198 KB/s) - Control connection closed. 
Retrying. 

--2009-07-09 12:06:18-- ftp://some_server/some_file 
    (try: 2) => `some_file' 
Connecting to some_server|0.0.0.0|:21... connected. 
Logging in as some_user ... Logged in! 
==> SYST ... done. ==> PWD ... done. 
==> TYPE I ... done. ==> CWD not needed. 
==> SIZE some_file ... 229376897 
==> PASV ... done. ==> REST 229376897 ... done.  
==> RETR some_file ... done. 
Length: 229376897 (219M), 0 (0) remaining 

100%[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++] 229,376,897 --.-K/s in 0s  

2009-07-09 12:06:18 (0.00 B/s) - `some_file' saved [229376897] 

Répondre

0

Je pense qu'un certain débogage pourrait être utile. Pourriez-vous plier la classe ci-dessous dans votre code? (Je ne l'ai pas fait moi-même car je sais que cette version fonctionne, et je ne voulais pas risquer de faire une erreur.) Vous devriez pouvoir placer la classe en haut de votre fichier et remplacer le corps de la boucle par ce que J'ai écrit après #LOOP BODY)

class CounterFile(): 
    def __init__(self, file, maxsize): 
     self.file = file 
     self.count = 0 
     self.maxsize = maxsize 

    def write(self, bytes): 
     self.count += len(bytes) 
     print "total %d bytes/%d"%(self.count, self.maxsize) 
     if self.count == self.maxsize: 
      print " Should be complete" 
     self.file.write(bytes) 


from ftplib import FTP 
ftp = FTP('ftp.gimp.org') 
ftp.login('ftp', '[email protected]') 
ftp.set_debuglevel(2) 

ftp.cwd('/pub/gimp/v2.6/') 
fname = 'gimp-2.6.2.tar.bz2' 

# LOOP BODY 
sz = ftp.size(fname) 
if sz is None: 
    print "Could not get size!" 
    sz = 0 
ret_status = ftp.retrbinary('RETR ' + fname, CounterFile(open(fname, 'wb'), sz).write) 
+0

C'est un ancien article mais aviez-vous vraiment envie d'inclure votre identifiant dans ce fichier? –

+0

se connecter en tant que "ftp" équivaut à se connecter en tant que "anonyme", et le mot de passe est alors traditionnellement défini sur l'adresse e-mail. Mon email est assez facile à déduire de mon nom de connexion stackoverflow, de toute façon. –

0

Je ne l'ai jamais utilisé ftplib, mais peut-être que vous pourriez faire:

  1. obtenir le nom et la taille du fichier que vous voulez.
  2. Démarrez un nouveau thread démon pour télécharger le fichier.
  3. Dans le thread principal, vérifiez toutes les quelques secondes si la taille du fichier sur le disque est égale à la taille cible.
  4. Si tel est le cas, attendez quelques secondes pour que la connexion se ferme correctement, puis quittez le programme.
Questions connexes