1

我使用ftputil从 FTP 服务器下载了一批文件。它引发了错误ftputil.error.FTPIOError: [Errno 60] Operation timed out

文档 - ftputil中所述,

keep_alive()尝试保持与远程服务器的连接处于活动状态,以防止发生超时。此方法主要用于在上传或下载文件时保持 FTPHost 对象的底层 FTP 连接处于活动状态。这将需要一个额外的线程,而上传或下载正在进行或keep_alivecallback函数调用。

keep_alive从一个callback函数中调用,

ftp_host.download(source, target, callback=ftp_host.keep_alive) 

但它提出了ERROR __main__ keep_alive() takes 1 positional argument but 2 were given

如何保持 FTP 连接处于活动状态?

4

1 回答 1

1

这不是您问题的直接答案,但它可能有助于您自己找到特定问题的答案。此外, ftputil 网站上的一张票更有助于调试问题。也就是说,我认为可以先询问 StackOverflow,因为您事先不知道问题是否简单。:-)

由于 FTP 是有状态协议,客户端和服务器不能在给定时间发送任意命令。允许的命令和可能的回复由连接所处的状态决定。另见RFC 959中的状态图。

为了解决这个限制,ftputil 在后台为每个远程文件对象创建一个新的 FTP 连接 [1]。使用这种方法,您仍然chdir可以在另一个仍在进行中时发送类似命令或开始下载。但是,这意味着从服务器的角度来看,所有这些来自单个FTPHost对象的 FTP 连接都是独立的连接,因此这些连接中的每一个都可以有不同的超时时间,具体取决于各个连接的使用模式。

例如,存在ftputil ticket 141,其中可能由对象启动的主连接FTPHost超时,而用于下载的连接仍然可用。

在您的情况下,找出哪些底层连接超时(初始连接或远程文件的连接)可能会有所帮助。您可以使用ftputil.session.session_factory创建启用 FTP 调试的工厂(请参阅文档)。

不幸的是,60 秒的超时时间很短,因此超时的机会相对较多。

特别是考虑到 FTP 连接超时的可能性,我的建议是编写用于 FTP 传输的软件,以便您可以FTPHost在被超时中断的地方重新启动操作(理想情况下使用新对象以保持稳健性)。到目前为止,我还没有想出一种普遍解决超时问题的方法。在简单的情况下,您实际上可能会更好地ftplib直接使用,尽管 ftputil 具有没有的健壮性和延迟改进ftplib。使用ftplib不会使您免于超时,但至少您没有任何可能使调试更加困难的“隐藏”连接。


[1] 也就是说,如果您在 ftputil 中关闭远程文件,则可以重用底层 FTP 连接,除非它没有超时。库在重用连接之前检查超时。

由于 ftputil 缓存了来自服务器的大量信息以减少延迟,有关超时的情况更加复杂。例如,如果您调用FTPHost.getcwd(),则从缓存属性中检索当前目录,而不是通过向服务器发送PWD命令从而重置超时。来自目录列表的统计信息通常也被缓存。

于 2021-05-01T14:32:36.737 回答