ftplib - создание файла очень медленное: SSLError: Тайм-аут операции чтения

import ftplib
import csv
import StringIO

sio = StringIO.StringIO()
data = csv.writer(sio)
data.writerows(data_to_export)
sio.seek(0)
ftps.storbinary("STOR " + 'blah.csv', sio)
ftps.close()

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

    ftps.storbinary("STOR " + 'blah.csv', sio)
  File "/usr/lib/python2.7/ftplib.py", line 752, in storbinary
    conn.unwrap()
  File "/usr/lib/python2.7/ssl.py", line 384, in unwrap
    s = self._sslobj.shutdown()
SSLError: The read operation timed out

Я не понимаю, почему это так медленно и почему это дает время ожидания, даже если он создает этот файл.

PS, пожалуйста, спросите, если мне нужно предоставить дополнительную информацию

Обновление я тоже пробовал cString, но это ничего не улучшает, так как я думаю, это не связано со скоростью записи.

Если есть какая-либо разница, соединение с ftp выполняется с использованием режима Implicit SSL/TLS (этот ftp не поддерживает явный SSL/TLS).

Обновление копай глубже. Вот что показывает отладка для ftp:

*cmd* 'TYPE I'
*resp* '200 Binary mode selected.'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (*,*,*,*,*,*)'
*cmd* 'STOR blah.csv'
*resp* '125 Secure data connection open; transfer starting.'

И затем застревает на этом последнем выходе, пока я не получу время соединения.

Примечание Мое интернет-соединение очень хорошее, но этот ftp довольно медленный. Тем не менее, я думаю, что такой маленький файл должен обрабатываться гораздо быстрее, чем этот.

Update2 Это какой-то странный ftp. При попытке небезопасного подключения по FTP, файлы загружаются правильно и быстро. Это неявное соединение как-то связано с низкой производительностью и временем ожидания.

2 ответа

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

Обратите внимание, что это файл гораздо большего размера, но он извлек соответствующие разделы, поэтому игнорируйте некоторые переменные, например, args.var. Возможно, вам придется настроить размер блока в зависимости от пропускной способности и т. Д., Попробуйте уменьшить его до 1024, а затем продолжить работу.

Надеюсь, поможет

def initiate_ftp_connection(ftp_host, user, passwd, ftp_dir):
    ftp_session = ftplib.FTP()
    ftp_session.connect(ftp_host, 21)
    #uncomment for debugging.
    #ftp_session.set_debuglevel(2)
    ftp_session.login(user=user, 
                      passwd=passwd)
    #cd to correct remote directory
    ftp_session.cwd(ftp_dir)
    return ftp_session



def upload_deliverables(session, file_and_path):
    working_dir = os.path.dirname(file_and_path)
    #strip to remove any newlines
    filename = os.path.basename(file_and_path).strip()
    totalSize = os.path.getsize(file_and_path)
    #instantiate progress tracker for status updates
    uploadTracker = FtpUploadTracker(int(totalSize),filename)
    #change dir to working_dir
    os.chdir(working_dir)
    '''
     Trigger the ftp upload (storbinary) for the deliverable.
      Args:
       1: FTP KEYWORD and FILE
       2: File IO
       3: Blocksize
       4: Callback
    '''
    session.storbinary('STOR ' + filename, 
                        open(filename,'r'), 
                        8192, 
                        uploadTracker.ftp_callback)


#connect to server
ftp_session = initiate_ftp_connection(args.ftp_host, 
                                      args.ftp_user, 
                                      args.ftp_pass,
                                      args.ftp_dir)

#start ftp delivery
upload_deliverables(ftp_session, args.asset)
#quit the ftp session
ftp_session.quit()   
#close any file handles.
ftp_session.close()

Я столкнулся с этой проблемой в функции STORBINARY при использовании Python ftplib.FTP_TLS, prot_pи FTP-сервер Microsoft.

Пример:

      ftps = FTP_TLS(host,username,password)
ftps.prot_p
STORBINARY...

Ошибка указывает на тайм-аут функции развертывания.

Это связано со следующими проблемами:

https://www.sami-lehtinen.net/blog/python-32-ms-ftps-ssl-tls-lockup-fix

https://bugs.python.org/issue10808

https://bugs.python.org/issue34557

Разрешение:

  1. Откройте страницу Python для ftplib: https://docs.python.org/3/library/ftplib.html .

  2. Нажмите на исходный код, который приведет вас к чему-то вроде этого: https://github.com/python/cpython/blob/3.10/Lib/ftplib.py .

  3. Создайте копию этого кода в своем проекте (пример: my_lib\my_ftplib.py)

  4. Для метода, который не работает, в вашем случае STORBINARY ошибка выглядит в строке, где написано conn.unwrap()в этом методе. Прокомментируйте эту строку. Введите ключевое слово passиначе пусто ifблок выдаст синтаксическую ошибку.

  5. Импортируйте указанную выше библиотеку в свой файл, где вы создаете экземпляр FTP_TLS. Теперь вы больше не столкнетесь с этой ошибкой.

Рассуждение: Код в функции def ntransfercmd(под FTP_LTSclass) заключает объект в сеанс SSL. Приведенная выше строка, которую вы прокомментировали, отвечает за отмену передачи после сеанса SSL. По какой-то причине при использовании FTP-сервера Microsoft код блокируется в этой строке и приводит к тайм-ауту. Это может быть либо из-за того, что после передачи сервер разрывает соединение, либо из-за того, что сервер разворачивает SSL со своей стороны. Я не уверена. Комментирование этой строки безвредно, потому что в конечном итоге соединение все равно будет закрыто — подробности см. Ниже:

В коде ftplib на Python вы заметите, что connобъект в функции STORBINARY заключен в блок, и что он создан с использованием socket.create_connection. Это означает, что .close()автоматически вызывается, когда код выходит из withблок (вы можете убедиться в этом, взглянув на __exit__метод в исходном коде класса сокетов Python).

Другие вопросы по тегам