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!

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top