我用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