问题本身
在请求 get(...).raw期间,我们得到了一个原始的urllib3.HTTPResponse类。由于其IO功能,这很好并且打算拥有。考虑到我真的不想修补,有没有办法告诉这个类嘿,看,我正在做raw.read()每次迭代都使用网络以避免一次读取太多数据来自大文件,所以如果在那段时间 ECONNRESET 来自服务器端,解决连接并继续它离开的地方?
服务器端是外部的,也就是我无法管理的,只有客户端。
我认为没有任何可能的方法可以重试此错误,即使使用 urllib3 的 util.Retry 类在本地调试使用的库本身也是如此。有点可能类似的追溯和问题在这里:https ://github.com/urllib3/urllib3/issues/1331
代码示例来说明
import requests
raw = requests.get('http://httpbin.org/stream/20', stream=True).raw
while not line := raw.read(chunk_size=16):
print line
追溯:
Traceback (most recent call last):
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py",
line 317, in recv_into
return self.connection.recv_into(*args, **kwargs)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
self._raise_ssl_error(self._ssl, result)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1614, in _raise_ssl_error
raise WantReadError()
OpenSSL.SSL.WantReadError
During handling of the above exception, another exception occurred:Traceback (most recent call last):
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 317, in recv_into
return self.connection.recv_into(*args, **kwargs)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
self._raise_ssl_error(self._ssl, result)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1614, in _raise_ssl_error
raise WantReadError()
OpenSSL.SSL.WantReadError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 317, in recv_into
return self.connection.recv_into(*args, **kwargs)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1814, in recv_into
self._raise_ssl_error(self._ssl, result)
File "/python3.8/site-packages/OpenSSL/SSL.py", line 1631, in _raise_ssl_error
raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/python3.8/site-packages/urllib3/response.py", line 438, in _error_catcher
yield
File "/python3.8/site-packages/urllib3/response.py", line 519, in read
data = self._fp.read(amt) if not fp_closed else b""
File "/python3.8/http/client.py", line 455, in read
n = self.readinto(b)
File "/python3.8/http/client.py", line 499, in readinto
n = self.fp.readinto(b)
File "/python3.8/socket.py", line 669, in readinto
return self._sock.recv_into(b)
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into
return self.recv_into(*args, **kwargs)
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into
return self.recv_into(*args, **kwargs)
File "/python3.8/site-packages/urllib3/contrib/pyopenssl.py", line 322, in recv_into
raise SocketError(str(e))
OSError: (104, 'ECONNRESET')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/My-Code-Calls-With_Fancypath/file.py", line XYZ, in func_name
...
File "/python3.8/site-packages/urllib3/response.py", line 541, in read
raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
File "/python3.8/contextlib.py", line 131, in __exit__
self.gen.throw(type, value, traceback)
File "/python3.8/site-packages/urllib3/response.py", line 455, in _error_catcher
raise ProtocolError("Connection broken: %r" % e, e)
urllib3.exceptions.ProtocolError: ('Connection broken: OSError("(104, \'ECONNRESET\')")', OSError("(104, 'ECONNRESET')"))
与我的问题有些相似的问题是:Python Requests package: lost connection while streaming。唯一的区别是,接受的答案会重试整个下载。
环境:
pyOpenSSL==18.0.0 urllib3==1.26.5 请求==2.25.1 python==3.8
最后
让我们假设理论上这种方式是不可能的。在不改变很多行为的情况下,您有什么好的建议吗?就像使用 urllib3.HTTPResponse.iter_content(...) 方法一样(尽管它的文档说NOT REENTRANT SAFE :( )?