Python FTP套接字超时处理

7

我用Python35的ftplib处理socket超时时遇到了问题。当发生socket超时错误时,由于某种原因我无法捕获异常,脚本仍会引发错误并退出。以下是相关代码块:

    try:
        ftp = FTP(self.config.base_url, timeout=400)
        ftp.login()
        ftp.cwd(self.config.root_path)
        ftp.retrbinary("RETR {0}".format(os.path.join(self.root_path, file_path)), fp.write, 1024)
        ftp.quit()
    except socket.timeout:
        self.download_file(file_path)

由于某些原因,这个脚本仍然会出现套接字超时异常,这是怎么可能的?通用的 catch-all 也不起作用。以下是错误的堆栈跟踪:
File "ftp.py", line 82, in __init__
  self.ftp = FTP(self.config.base_url, timeout=400)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ftplib.py", line 118, in __init__
  self.connect(host)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ftplib.py", line 156, in connect
  self.welcome = self.getresp()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ftplib.py", line 235, in getresp
  resp = self.getmultiline()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ftplib.py", line 221, in getmultiline
  line = self.getline()
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ftplib.py", line 203, in getline
  line = self.file.readline(self.maxline + 1)
File "/opt/local/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socket.py", line 576, in readinto
  return self._sock.recv_into(b)
socket.timeout: timed out

如您所见,这是抛出的socket.timeout错误,那么为什么没有被捕获?在经过数小时的互联网研究后,我无法找到任何有用的信息来解决此问题,如能提供任何有关此问题的见解,将不胜感激。
供参考,以下是socket.py的相关代码块:
 def readinto(self, b):
    """Read up to len(b) bytes into the writable buffer *b* and return
    the number of bytes read.  If the socket is non-blocking and no bytes
    are available, None is returned.

    If *b* is non-empty, a 0 return value indicates that the connection
    was shutdown at the other end.
    """
    self._checkClosed()
    self._checkReadable()
    if self._timeout_occurred:
        raise OSError("cannot read from timed out object")
    while True:
        try:
            return self._sock.recv_into(b)
        except timeout:
            self._timeout_occurred = True
            raise
        except error as e:
            if e.args[0] in _blocking_errnos:
                return None
            raise

更新: 看起来问题在于如果传递给FTP构造函数的超时时间大于套接字超时时间的默认值,则ftplib的行为是出乎意料的。在此编辑时,存在一个开放的Python问题来解决这种行为:http://bugs.python.org/issue30956

1个回答

0
尝试添加。

ftp.set_pasv(False)

禁用被动模式应该可以解决问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接