Python: загрузка файла с использованием ftplib навсегда зависает после успешной загрузки файла

208
Manish Mehra

Я пытался решить проблему, когда мы загружаем файл с ftp / ftps. Файл успешно загружен, но после завершения загрузки файла операции не выполняются. Не произошло ошибок, которые могли бы дать больше информации о проблеме. Я попытался найти это в stackoverflow и нашел эту ссылку, в которой говорится о похожей формулировке проблемы и похоже, что я столкнулся с похожей проблемой, хотя я не уверен. Нужна немного больше помощи в решении проблемы.

Я попытался установить тайм-аут соединения FTP на 60 минут, но с меньшей помощью. До этого я использовал retrbinary () из ftplib, но там возникает та же проблема. Я попытался передать разные размеры блоков и окон, но с этим также проблема была воспроизводимой.

Я пытаюсь загрузить файл размером ~ 3 ГБ из кластера AWS EMR. Пример кода написан ниже

def download_ftp(self, ip, port, user_name, password, file_name, target_path): try: os.chdir(target_path) ftp = FTP(host=ip) ftp.connect(port=int(port), timeout=3000) ftp.login(user=user_name, passwd=password)  if ftp.nlst(file_name) != []: dir = os.path.split(file_name) ftp.cwd(dir[0]) for filename in ftp.nlst(file_name): sock = ftp.transfercmd('RETR ' + filename)  def background(): fhandle = open(filename, 'wb') while True: block = sock.recv(1024 * 1024) if not block: break fhandle.write(block) sock.close()  t = threading.Thread(target=background) t.start() while t.is_alive(): t.join(60) ftp.voidcmd('NOOP') logger.info("File " + filename + " fetched successfully") return True else: logger.error("File " + file_name + " is not present in FTP")  except Exception, e: logger.error(e) raise 

Другой вариант, предложенный в вышеупомянутой ссылке, - закрыть соединение после загрузки небольшого фрагмента файла, а затем перезапустить соединение. Может кто-нибудь подсказать, как этого можно добиться, не уверенный, как возобновить загрузку с той же точки, где загрузка файла была остановлена ​​в последний раз перед закрытием соединения. Будет ли этот метод полным доказательством загрузки всего файла.

Я не очень разбираюсь в настройках тайм-аута на уровне FTP-сервера, поэтому не знал, что и как нужно изменить. Я в основном хочу написать общий загрузчик FTP, который может помочь в загрузке файлов с FTP / FTPS.

Когда я использую метод retrbinary () в ftplib и устанавливаю уровень отладки 2.

ftp.set_debuglevel(2) 

Ниже журналы печатаются.

cmd 'TYPE I' положить 'TYPE I \ r \ n' get '200 Тип установлен в I. \ r \ n' соответственно '200 Тип установлен в I.' cmd 'PASV' put 'PASV \ r \ n' get '227 Вход в пассивный режим (64,27,160,28,133,251). \ r \ n' resp '227 Вход в пассивный режим (64,27,160,28,133,251).' cmd 'RETR FFFT_BRA_PM_R_201711.txt' положить 'RETR FFFT_BRA_PM_R_201711.txt \ r \ n' получить '150 Открытие соединения для передачи данных в режиме BINARY для FFFT_BRA_PM_R_201711.txt. \ r \ n' или для открытия_RB_F_F_F_F_11_201_11.

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

Как мне добиться того же в коде Python?

1

0 ответов на вопрос