Synchronisation des répertoires avec le FTPLIB de Python
-
14-11-2019 - |
Question
J'apprends Python et j'essaie d'écrire un code pour synchroniser deux répertoires: l'un est sur FTP Server, l'autre est sur mon disque local. Jusqu'à présent, j'ai écrit un code de travail mais j'ai une question ou deux à ce sujet :)
import os
from ftplib import FTP
h_local_files = [] # create local dir list
h_remote_files = [] # create remote dir list
h_local = 'C:\\something\\bla\\' # local dir
ftp = FTP('ftp.server.com')
ftp.login('user', 'pass')
if os.listdir(h_local) == []:
print 'LOCAL DIR IS EMPTY'
else:
print 'BUILDING LOCAL DIR FILE LIST...'
for file_name in os.listdir(h_local):
h_local_files.append(file_name) # populate local dir list
ftp.sendcmd('CWD /some/ftp/directory')
print 'BUILDING REMOTE DIR FILE LIST...\n'
for rfile in ftp.nlst():
if rfile.endswith('.jpg'): # i need only .jpg files
h_remote_files.append(rfile) # populate remote dir list
h_diff = sorted(list(set(h_remote_files) - set(h_local_files))) # difference between two lists
for h in h_diff:
with open(os.path.join(h_local,h), 'wb') as ftpfile:
s = ftp.retrbinary('RETR ' + h, ftpfile.write) # retrieve file
print 'PROCESSING', h
if str(s).startswith('226'): # comes from ftp status: '226 Transfer complete.'
print 'OK\n' # print 'OK' if transfer was successful
else:
print s # if error, print retrbinary's return
Ce morceau de code devrait faire deux listes Python: une liste de fichiers dans le répertoire local et une liste de fichiers dans le répertoire FTP. Après avoir supprimé les doublons des listes, le script doit télécharger des fichiers «manquants» dans mon répertoire local.
Pour l'instant, ce morceau de code fait ce dont j'ai besoin, mais j'ai remarqué que lorsque je l'exécute, ma sortie n'agit pas comment j'imagine qu'elle agirait :)
Par exemple, ma sortie actuelle va:
PROCESSING 2012-01-17_07.05.jpg
OK
# LONG PAUSE HERE
PROCESSING 2012-01-17_07.06.jpg
OK
# LONG PAUSE HERE
PROCESSING 2012-01-17_07.06.jpg
OK
etc...
Mais j'imagine que cela devrait fonctionner comme ceci:
PROCESSING 2012-01-17_07.05.jpg
# LONG PAUSE HERE (WHILE DOWNLOADING)
OK
PROCESSING 2012-01-17_07.06.jpg
# LONG PAUSE HERE (WHILE DOWNLOADING)
OK
PROCESSING 2012-01-17_07.06.jpg
# LONG PAUSE HERE (WHILE DOWNLOADING)
OK
etc...
Comme je l'ai dit, j'ai juste commencé à apprendre Python, et peut-être que je fais des trucs ici complètement mal (if str(s).startswith('226')
????). Peut-être que je ne peux pas réaliser cela avecftplib
seulement? Donc, à la fin, mes questions sont:
Qu'est-ce que je fais de mal ici? :)
Comment produire une sortie «appropriée» et existe-t-il un moyen d'imprimer une sorte de statut lors du téléchargement d'un fichier (au moins une ligne de points), par exemple:
PROCESSING 2012-01-17_07.05.jpg
..........
OK
PROCESSING 2012-01-17_07.06.jpg
......
OK
PROCESSING 2012-01-17_07.06.jpg
...............
OK
etc...
Merci beaucoup pour votre aide!
La solution
Blocs rerybinary jusqu'à ce qu'il soit terminé. C'est pourquoi tu vois Processing ZZZ\n OK
Immédiatement, car il se produit une fois l'appel à Retrbinary terminé.
Si vous souhaitez imprimer .
Pour chaque appel, vous devez ensuite fournir une fonction de rappel pour ce faire. Voici le docstring pour Retrbinary:
"""Retrieve data in binary mode. A new port is created for you.
Args:
cmd: A RETR command.
callback: A single parameter callable to be called on each
block of data read.
blocksize: The maximum number of bytes to read from the
socket at one time. [default: 8192]
rest: Passed to transfercmd(). [default: None]
Returns:
The response code.
"""
Ainsi, vous devez fournir un rappel différent qui écrit à la fois le fichier et imprime '. "
import sys # At the top of your module.
# Modify your retrbinary
ftp.retrbinary('RETR ' + h, lambda s: ftpfile.write(s) and sys.stdout.write('.'))
Vous devrez peut-être modifier cet extrait de code, mais cela devrait vous donner une idée de ce qu'il faut faire.