如何延迟抛出urllib3的NewConnectionError异常且不修改源码?
解决方案
方法1:猴子补丁捕获暂存异常
通过猴子补丁改写urllib3的连接方法,捕获NewConnectionError并暂存,待需要时再抛出,无需修改库源码:
import urllib3 from urllib3.exceptions import NewConnectionError # 全局列表存储暂存的异常 pending_exceptions = [] # 保存原始连接方法 original_connect = urllib3.connection.HTTPConnection.connect def patched_connect(self): try: original_connect(self) except NewConnectionError as e: # 将异常存入全局列表,不立即抛出 pending_exceptions.append(e) # 若需让后续代码正常执行,可根据业务场景构造模拟响应 # 例如:如果使用requests,可返回一个假的响应对象(需适配调用逻辑) # 应用补丁,需确保在requests等依赖库导入前执行 urllib3.connection.HTTPConnection.connect = patched_connect # 在合适时机抛出暂存的异常 if pending_exceptions: # 可选择抛出第一个异常,或遍历抛出全部 raise pending_exceptions[0]
方法2:上下文管理器包裹代码块
若明确哪些代码会触发异常,用上下文管理器捕获并暂存:
from urllib3.exceptions import NewConnectionError pending_exceptions = [] class HoldConnectionErrors: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is NewConnectionError: pending_exceptions.append(exc_val) return True # 标记异常已处理,阻止向上抛出 return False # 使用示例 with HoldConnectionErrors(): # 放入可能触发拒绝连接异常的代码 import requests requests.get("http://localhost:9999") # 后续需要时抛出异常 if pending_exceptions: raise pending_exceptions[0]
关键注意点
- 猴子补丁必须在
requests等依赖urllib3的库导入前执行,否则补丁不会生效。 - 若后续代码依赖请求成功的结果,需构造适配业务的模拟响应,避免逻辑崩溃。
- 可在暂存异常时额外记录请求URL、时间等上下文信息,方便后续排查。
内容的提问来源于stack exchange,提问作者Achilleas Yfantis
相关产品推荐
相关产品推荐

