Синхронизация каталогов с помощью ftplib Python - PullRequest
3 голосов
/ 25 января 2012

Я изучаю python и пытаюсь написать код для синхронизации двух каталогов: один на ftp-сервере, другой на моем локальном диске.До сих пор я написал рабочий код, но у меня есть вопрос или два по этому поводу:)

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

Этот фрагмент кода должен составить два списка Python: список файлов в локальном каталоге и список файловв каталоге ftp.После удаления дубликатов из списков скрипт должен загрузить «отсутствующие» файлы в мой локальный каталог.

Пока этот фрагмент кода делает то, что мне нужно, но я заметил, что когда я запускаю его, мой выводне действует так, как я себе представляю:)

Например, мой токовый вывод выглядит так:

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...

, но я думаю, что он должен работать так:

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...

Как я уже сказал, я только начал изучать Python, и, возможно, я делаю некоторые вещи здесь совершенно неправильно (if str(s).startswith('226') ????).Может быть, я не могу добиться этого только с ftplib?Итак, в конце мои вопросы:

Что я здесь не так делаю?:)
Как создать «правильный» вывод и есть ли способ напечатать какой-либо статус при загрузке файла (по крайней мере, строку точек), например:

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...

Спасибомного за помощь!

1 Ответ

3 голосов
/ 25 января 2012

повторных блоков до его завершения. Вот почему вы видите Processing ZZZ\n OK сразу, потому что это происходит после завершения вызова retrbinary.

Если вы хотите печатать . для каждого вызова, то вам нужно предоставить функцию обратного вызова для этого. вот строка документации для 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.
    """

Итак, вам нужно предоставить другой обратный вызов, который одновременно записывает файл и печатает '.'

import sys # At the top of your module.

# Modify your retrbinary    
ftp.retrbinary('RETR ' + h, lambda s: ftpfile.write(s) and sys.stdout.write('.'))

Возможно, вам придется отредактировать этот фрагмент кода, но он должен дать вам представление о том, что делать.

...