ftp.retrbinary () help python - PullRequest
       25

ftp.retrbinary () help python

9 голосов
/ 15 января 2011

Я создал скрипт Python для подключения к remserver.

datfile = []
for dk in range(len(files)):
  dfnt=files[dk]
  dpst=dfnt.find('.dat')
  if dpst == 15:
    dlist = dfnt[:]
    datfile.append(dlist)

    assert datfile == ['a.dat','b.dat']
    # True

Который, как вы можете видеть, создает список. Сейчас я передаю этот список на

ftp.retrbinary('datfile')

но эта строка возвращает ошибку:

typeerror: retrbinary() takes at least 3 arguments (2 given)

не уверены, что ищете?

1 Ответ

27 голосов
/ 15 января 2011

Это говорит о том, что вы не предоставляете достаточное количество аргументов для метода retrbinary.

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

В качестве примечания вы можете спросить, почему в нем говорится, что для аргументов требуется «3», а не «2». Это потому, что он также считает аргумент 'self', который требуется Python для методов экземпляра, но вы неявно передаете его с помощью ftp ссылки на объект.

РЕДАКТИРОВАТЬ - Похоже, я не совсем ответил на ваш вопрос.

Для аргумента command предполагается, что вы передаете правильную команду RETR, а не список.

filenames = ['a.dat', 'b.dat']

# Iterate through all the filenames and retrieve them one at a time
for filename in filenames:
    ftp.retrbinary('RETR %s' % filename, callback)

Для callback вам нужно передать что-нибудь вызываемое (обычно это какая-то функция), которое принимает один аргумент. Аргумент является порцией данных из файла, который извлекается. Я говорю «чанк», потому что когда вы перемещаете большие файлы, вам редко хочется хранить весь файл в памяти. Библиотека предназначена для итеративного вызова вашего обратного вызова при получении кусков данных. Это позволяет вам записывать фрагменты файла, поэтому в любой момент времени вам нужно только сохранить относительно небольшой объем данных в памяти.

Мой пример здесь немного продвинут, но ваш обратный вызов может быть закрытием внутри цикла for, который записывает в открытый файл:

import os

filenames = ['a.dat', 'b.dat']

# Iterate through all the filenames and retrieve them one at a time
for filename in filenames:
    local_filename = os.path.join('/tmp', filename)

    # Open a local file for writing (binary mode)...
    # The 'with' statement ensures that the file will be closed 
    with open(local_filename, 'wb') as f:
        # Define the callback as a closure so it can access the opened 
        # file in local scope
        def callback(data):
            f.write(data)

        ftp.retrbinary('RETR %s' % filename, callback)

Это также можно сделать более кратко с помощью оператора lambda, но я нахожу людей, плохо знакомых с Python, и некоторые из его концепций функционального стиля легче понимают первый пример. Тем не менее, вот вместо этого вызов ftp с лямбдой:

ftp.retrbinary('RETR %s' % filename, lambda data: f.write(data))

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

ftp.retrbinary('RETR %s' % filename, f.write)

Все три из этих примеров должны быть аналогичными, и, надеюсь, их прохождение поможет вам понять, что происходит.

Я исключил любую обработку ошибок для примера.

Кроме того, я не тестировал ни один из приведенных выше кодов, поэтому, если он не работает, дайте мне знать, и я посмотрю, смогу ли я уточнить это.

...