Есть ли особый трюк для загрузки zip-файла и записи его на диск с помощью Python?

Я загружаю zip-файл с удаленного FTP-сайта, используя Python ftplib. Затем я пытаюсь записать его на диск. Запись файла работает, однако большинство попыток открыть zip с помощью WinZip или WinRar терпят неудачу; оба приложения утверждают, что файл поврежден. Однако, как ни странно, если щелкнуть правой кнопкой мыши и попытаться извлечь файл с помощью WinRar, файл будет извлечен.

Чтобы было ясно, запись в файл будет работать, но не будет открывать в популярных zip-приложениях, а будет распаковываться с помощью тех же приложений. Обратите внимание, что модуль ZIP-файлов Python никогда не может распаковать ZIP-файлы.

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

filedata = None
def appender(chunk):
    global filedata
    filedata += chunk


def getfile(filename):
  try:
      ftp = None

      try:
          ftp = FTP(address)
          ftp.login('user', 'password')

      except Exception, e:
          print e

      command = 'RETR ' + filename

      idx = filename.rfind('/')
      path = filename[0:idx]
      ftp.cwd(path)
      fileonly = filename[idx+1:len(filename)]

      ftp.retrbinary('RETR ' + filename, appender)

      global filedata
      data = filedata

      ftp.close()

      filedata = ''
      return data

  except Exception, e:
      print e

data = getfile('/archives/myfile.zip')    
file = open(pathtoNTFileShare, 'wb')
file.write(data)
file.close()

person ApplePieIsGood    schedule 23.02.2009    source источник


Ответы (2)


Передайте file.write непосредственно внутри функции retrbinary вместо передачи appender. Это сработает и не будет использовать столько оперативной памяти при загрузке большого файла.

Если вы хотите, чтобы данные хранились внутри переменной, вы также можете иметь переменную с именем:

blocks = []

Затем перейдите к retrbinary вместо appender:

blocks.append

Ваша текущая функция добавления неверна. += не будет работать правильно, когда есть двоичные данные, потому что он попытается добавить строку и остановится на первом увиденном NULL.

Как уже упоминал @Lee B, вы также можете использовать urllib2 или Curl. Но ваш текущий код почти правильный, если вы сделаете небольшие изменения, о которых я упоминал выше.

person Brian R. Bondy    schedule 23.02.2009

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

Глядя на ваш код, я вижу пару неправильных вещей. Ваш захват исключения только печатает исключение, а затем продолжается. Для фатальных ошибок, таких как отсутствие соединения FTP, им необходимо распечатать сообщение, а затем выйти. Кроме того, ваши файловые данные начинаются как None, затем ваш аппендер использует +=, чтобы добавить к этому, поэтому вы пытаетесь добавить строку + None, что дает TypeError, когда я пытаюсь это сделать здесь. Я удивлен, что это вообще работает; Я бы предположил, что приложение выдаст исключение, и поэтому FTP-копия прервется.

Перечитывая, я только что заметил еще один ответ об использовании += для двоичных данных. Это вполне могло быть так; python иногда пытается быть умным и может «помогать», когда вы соединяете строки с пробелами или NUL в них или что-то в этом роде. Лучше всего открыть файл (назовем его outfile) и использовать приложение для просто outfile.write(chunk).

person Lee B    schedule 23.02.2009
comment
Я должен был сказать, что убрал всю реальную обработку исключений, это только основы, чтобы показать проблему. - person ApplePieIsGood; 23.02.2009