【问题标题】:Cannot catch requests.exceptions.ConnectionError with try except无法使用 try except 捕获 requests.exceptions.ConnectionError
【发布时间】:2022-11-27 19:45:31
【问题描述】:

感觉我正在慢慢失去理智。我无法捕获 REST-API 请求中的连接错误。我在 stackoverflow 上阅读了至少 20 个类似的问题,尝试了我能想到的所有可能的 except 语句,并尽可能地简化代码以排除某些其他库。

我正在使用 Python 3.7 并请求 2.25.1。这是对我自己的服务器上的 API 的非常基本的调用,有时会失败,但偶尔会失败一次:

try:
    response = requests.get(url, headers=api_headers, auth=HTTPBasicAuth(username, password))
except requests.exceptions.ConnectionError:
     print("Connection error!")
     

很抱歉,我无法提供完整的工作示例,因为我没有连接到可公开访问的 API,所以我不得不删除 url、用户名和密码。

即使我尝试捕获连接错误,脚本也会失败并出现以下回溯:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 706, in urlopen
    chunked=chunked,
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 421, in connect
    tls_in_tls=tls_in_tls,
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\ssl_.py", line 429, in ssl_wrap_socket
    sock, context, tls_in_tls, server_hostname=server_hostname
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\ssl_.py", line 472, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 412, in wrap_socket
    session=session
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 850, in _create
    self.do_handshake()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 1108, in do_handshake
    self._sslobj.do_handshake()
TimeoutError: [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 756, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\retry.py", line 532, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\packages\six.py", line 734, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 706, in urlopen
    chunked=chunked,
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 421, in connect
    tls_in_tls=tls_in_tls,
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\ssl_.py", line 429, in ssl_wrap_socket
    sock, context, tls_in_tls, server_hostname=server_hostname
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\ssl_.py", line 472, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 412, in wrap_socket
    session=session
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 850, in _create
    self.do_handshake()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\ssl.py", line 1108, in do_handshake
    self._sslobj.do_handshake()
urllib3.exceptions.ProtocolError: ('Connection aborted.', TimeoutError(10060, 'Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat', None, 10060, None))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\adapters.py", line 498, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', TimeoutError(10060, 'Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat', None, 10060, None))

我不明白如果我捕获到那个错误,脚本怎么可能因 requests.exceptions.ConnectionError 而失败?

如果我正确理解回溯,错误不会在我的代码中抛出,因此我无法捕捉到它?我所看到的只是 python 库,如 ssl.py 和 urllib 以及请求,但不是我的代码中的一行。那我怎么抓住它呢?

非常感谢任何帮助!

编辑(因为这在评论中是不可能的)。 @Thomas 发表了一条有用的评论以连接到 httpstat.us:81 进行调试。所以我尝试用 response = requests.get("http://httpstat.us:81") 替换我的 order_response = requests.get() 电话。这是我的代码中的确切块:

try:
    order_response = requests.get(order_access_url, headers=api_headers, auth=HTTPBasicAuth(username, password))
    if order_response.status_code == 200:
        order_content = json.loads(order_response.text)
    else:
        order_content = ""
except requests.exceptions.ConnectionError:
    print("Connection error!")

如果我尝试连接到http://httpstat.us:81,它实际上会捕获错误。如果我故意不抓住它,错误看起来像这样:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 170, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\connection.py", line 96, in create_connection
    raise err
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\connection.py", line 86, in create_connection
    sock.connect(sa)
TimeoutError: [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 706, in urlopen
    chunked=chunked,
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 394, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 234, in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1229, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1275, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1224, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 1016, in _send_output
    self.send(msg)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\http\client.py", line 956, in send
    self.connect()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 200, in connect
    conn = self._new_conn()
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connection.py", line 182, in _new_conn
    self, "Failed to establish a new connection: %s" % e
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x00000223F9B42860>: Failed to establish a new connection: [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\adapters.py", line 449, in send
    timeout=timeout
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\connectionpool.py", line 756, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\urllib3\util\retry.py", line 574, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='httpstat.us', port=81): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000223F9B42860>: Failed to establish a new connection: [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Daten\cloud.bss-archery.com\BSS\_Twain\modules\order_extracts_api.py", line 50, in create_order_analysis
    response = requests.get("http://httpstat.us:81")
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Tilman\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='httpstat.us', port=81): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x00000223F9B42860>: Failed to establish a new connection: [WinError 10060] Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat'))

所以我仍然很困惑,因为回溯中的最后一个条目实际上是相同的,requests.exceptions.ConnectionError,但它没有被我的真实应用程序捕获。然而,它是由 \lib\site-packages\requests\adapters.py 中的另一行提出的

【问题讨论】:

  • 你的脚本叫什么?
  • 那重要吗?名称是 order_extracts_api.py
  • 我从未见过未显示您的入口点的回溯,这就是我问的原因。我不知道你怎么没有调用堆栈上的东西
  • 是的,我也没有。这就是为什么我完全迷路了。我现在使用 Python 已经 5 年了,并且使用 try except 很多,我也阅读了很多回溯,这让我觉得自己完全是个初学者。
  • 这将是真的如果您无论如何都可以创建一个最小的可重现示例,那将很有帮助。您可以在接受连接后使用httpstat.us/200?sleep=5000 来提供缓慢的响应,并且(未记录的“功能”)httpstat.us:81 根本不接受连接。

标签: python python-3.x python-requests try-except


【解决方案1】:

好吧,我自己能想出来。有点儿。

一个大问题是回溯没有指向引发异常的代码行。我仍然不知道为什么会这样,以及这是否应该被视为请求中的错误。但无论如何:requests 在 adapters.py 中引发 ConnectionError 但起源是协议或套接字错误。这是 adapters.py 中的第 497 行:

except (ProtocolError, socket.error) as err:
    raise ConnectionError(err, request=request)

回溯中的 TimeoutError: [WinError 10060] 实际上指向套接字错误。

来自https://hstechdocs.helpsystems.com/manuals/globalscape/archive/cuteftp8/Socket_errors_10060_10061_10064_10065.htm

10060 范围内的套接字错误是 Winsock 错误。一般是出局连接问题,或者主机端连接问题。

这就是我无法使用 httpstat.us 重现错误的原因。

解决方案是将其作为 OSError 捕获:

try:
    response = requests.get(url, headers=api_headers, auth=HTTPBasicAuth(username, password))
except OSError as e:
     print(e)

老实说,这有点令人沮丧,因为我仍然不知道为什么引发 ConnectionError 的请求中的 ProtocolError 或 socket.error 需要用“OSError”捕获,但在这一点上,我很高兴我能找到任何解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 2021-06-27
    • 2012-04-14
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多