我正在使用Python的requests
模块通过SOCKS4代理连接到一个网站,当尝试连接到网站时,程序甚至无法连接到SOCKS4,因此PySocks模块抛出TimeoutError
异常,该异常被捕获并作为ProxyConnectionError
异常重新抛出。
如果这就是故事的结尾,我可以直接捕获ProxyConnectionError
,但是底层的urllib3
模块捕获异常并重新引发NewConnectionError
,您可以在官方源代码中看到这一点。
下面是我从程序中得到的最后一个回溯(为简洁起见,删掉了很多行):
Traceback (most recent call last):
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
socks.ProxyConnectionError: Error connecting to SOCKS4 proxy ...
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
urllib3.exceptions.NewConnectionError: <urllib3.contrib.socks.SOCKSHTTPSConnection object at 0x0000025DA70CCDC0>: Failed to establish a new connection: ...
During handling of the above exception, another exception occurred:
... (eventually raises requests.exceptions.ConnectionError, then terminates the program)
我的目标是捕获所有的PySocks错误(比如本例中引发的ProxyConnectionError
),这可以通过捕获基本异常类socks.ProxyError
来实现。
由于requests
库是一个下载的模块,我没有editing the underlying code的自由(如果我直接编辑源代码,那么如果其他人从PyPI下载我的代码并安装requests库,这些更改将不会更新)。
有没有办法捕获已经在另一个模块中捕获的错误?
1条答案
按热度按时间l7wslrjt1#
在做了一些挖掘之后,我发现了PEP responsible for adding
__context__
,这是异常对象上的一个属性,它允许隐式链接异常。这意味着对于每个异常,都有一个
__context__
属性指向之前捕获的异常,使用一点节点迭代,我们可以到达这个链的底部,它包含一个None
(如果它是第一个抛出的异常)。我把所有这些代码放在一起,编写了一个函数,它使用
sys.exc_info()
获取当前抛出的异常,然后迭代直到遇到None
,如果它找到之前抛出的异常,并且是我们要捕获的异常的子类,那么它返回True
:下面是我在代码中的用法: