【问题标题】:ftplib - file creation very slow: SSLError: The read operation timed outftplib - 文件创建速度非常慢:SSLError:读取操作超时
【发布时间】:2015-08-06 09:30:25
【问题描述】:
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

我不明白为什么它这么慢以及为什么它会超时,即使它创建了那个文件。

P.S.请询问我是否需要提供其他信息

更新 我也试过cString,但它并没有改善任何东西,因为我猜它与写入速度无关。

如果有任何区别,则使用隐式 SSL/TLS 模式连接到 ftp(即 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 有点慢。不过我想这么小的文件应该比这处理得快得多。

更新2 那是一些奇怪的ftp。尝试不安全的 ftp 连接,文件上传正确且快速。这种隐式连接与这种缓慢的性能和超时有关。

【问题讨论】:

    标签: python file ftp timeout ftplib


    【解决方案1】:

    关于速度,有太多因素需要猜测,所以我会调整代码并尝试以下我最近为客户 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()
    

    【讨论】:

    • 但这会从本地服务器/PC 上传文件。我需要直接在ftp中创建文件,因为该文件在本地服务器上不存在,它是在旅途中创建的。
    • 您仍然可以使用适用于一般上传的方法,对于您的文件,您需要查看 ftplib 的正确方法,您使用的是用于上传可交付成果的 storbinary,因此请尝试使用您自己的或使用“ftplib.storlines”的上述方法,以防万一? docs.python.org/2/library/ftplib.htmlsafaribooksonline.com/library/view/python-in-a/0596001886/…
    【解决方案2】:

    在使用 python 的 ftplib.FTP_TLSprot_p 和 Microsoft FTP 服务器时,我在 STORBINARY 函数上遇到了这个问题。

    例子:

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

    错误表明 unwrap 函数超时。

    与以下问题有关:

    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. 打开ftplib的python页面: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_LTS 类下)中的代码将conn 对象包含在一个SSL 会话中。您评论的上述行负责拆除 SSL 会话后传输。出于某种原因,当使用 Microsoft 的 FTP 服务器时,代码在该行被阻塞并导致超时。这可能是因为传输后服务器断开了连接,也可能是服务器从其一侧解开了 SSL。我不知道。评论该行是无害的,因为最终连接无论如何都会关闭 - 详情请参见下文:

    在 ftplib 的 python 代码中,您会注意到 STORBINARY 函数中的 conn 对象包含在 with 块中,并且它是使用 socket.create_connection 创建的。这意味着当代码退出with 块时会自动调用.close()(您可以通过查看python 套接字类源代码上的__exit__ 方法来确认这一点)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 2016-05-21
      • 2021-10-12
      相关资源
      最近更新 更多