Sincronización de directorios con ftplib de Python
-
14-11-2019 - |
Pregunta
Estoy aprendiendo Python e intento escribir un código para sincronizar dos directorios:uno está en el servidor ftp y el otro en mi disco local.Hasta ahora, escribí un código funcional pero tengo una o dos preguntas al respecto :)
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
Este fragmento de código debería crear dos listas de Python:una lista de archivos en el directorio local y una lista de archivos en el directorio ftp.Después de eliminar duplicados de las listas, el script debería descargar los archivos "faltantes" en mi directorio local.
Por ahora, este fragmento de código está haciendo lo que necesito, pero he notado que cuando lo ejecuto mi salida no actúa como imagino que actuaría :)
Por ejemplo, mi salida actual es:
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...
pero imagino que debería funcionar así:
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...
Como dije, recién comencé a aprender Python y tal vez estoy haciendo algunas cosas completamente mal (if str(s).startswith('226')
????).Tal vez no pueda lograr esto conftplib
¿solo?Entonces al final mis preguntas son:
¿Qué estoy haciendo mal aquí?:)
Cómo producir una salida "adecuada" y ¿hay alguna manera de imprimir algún tipo de estado mientras se descarga un archivo (al menos una línea de puntos), por ejemplo:
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...
¡Muchas gracias por ayudar!
Solución
bloques retrybinary hasta que se complete.Por eso ves Processing ZZZ\n OK
inmediatamente, porque ocurre después de que se haya completado la llamada a retrbinary.
Si quieres imprimir .
para cada llamada, debe proporcionar una función de devolución de llamada para hacer esto.aquí está la cadena de documentación para 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.
"""
Por lo tanto, debe proporcionar una devolución de llamada diferente que escriba el archivo e imprima '.'
import sys # At the top of your module.
# Modify your retrbinary
ftp.retrbinary('RETR ' + h, lambda s: ftpfile.write(s) and sys.stdout.write('.'))
Es posible que tengas que editar ese fragmento de código, pero debería darte una idea de qué hacer.