您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python:ftplib在传输结束时挂起

Python:ftplib在传输结束时挂起

没有更多信息,我实际上无法调试您的问题,因此我只能提出最一般的答案。这可能对您来说不是必需的,但对任何人来说都足够了。

retrbinary将阻塞直到整个文件完成。如果超过5分钟,则整个5分钟内都不会在控制通道上发送任何消息。您的客户端正在超时控制通道,或者服务器正在超时。因此,当您尝试与挂断时ftp.quit(),它将永远挂起或引发异常。

您可以使用构造timeout函数上的参数来控制一方的超时FTP。某些服务器支持IDLE命令,以允许您设置服务器端超时。但是,即使事实证明适当的超时也是可行的,您如何首先选择适当的超时时间呢?

您真正想做的是防止数据套接字上发生传输时控制套接字超时。但是如何?例如,如果您ftp.voidcmd('NOOP')经常在回调函数中使用它,就足以保持连接正常运行……但是这也将迫使您阻塞直到服务器响应NOOP,许多服务器在数据传输之前不会这样做已经完成,这意味着您将永远永久阻塞(或直到另一个超时),而不会获取数据。

处理两个套接字而一个不阻塞另一个套接字的标准技术是类似select.select或的多路复用器。您可以在此处执行此操作,但是您将不得不放弃使用简单的retrbinary接口,而是使用transfercmd显式获取数据套接字。

例如:

def downloadFile(…):
    ftp = FTP(…)
    sock = ftp.transfercmd('RETR ' + filename)
    def background():
        f = open(…)
        while True:
            block = sock.recv(1024*1024)
            if not block:
                break
            f.write(block)
        sock.close()
    t = threading.Thread(target=background)
    t.start()
    while t.is_alive():
        t.join(60)
        ftp.voidcmd('NOOP')

另一种解决方案是一次读取20MB,然后调用ftp.abort(),并使用rest参数恢复每个新retrbinary文件的传输,直到到达文件末尾。但是,这样ABOR可能会永远挂起NOOP,因此并不能保证任何事情,更不用说服务器不必对此做出响应了。

可以 做的就是关闭整个连接(不是quit,而是close)。这对服务器来说不是很好,并且可能导致重新发送一些浪费的数据,并且如果过快地杀死套接字,还可能阻止TCP正常加速到全速运行。但它应该工作。

python 2022/1/1 18:35:11 有600人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶