如何在Python中通用包装对象以捕获所有方法的异常?
通用包装Python对象捕获所有方法异常的方案(适配Bravado API测试)
刚好我之前做Bravado API测试的时候也碰到过一模一样的需求——不想手动写一堆重复的异常捕获代码,也不想为每个API端点都写包装类。用动态代理包装器就能完美解决,完全不用创建包含所有方法的新类,通用适配任何Python对象。
核心思路:用__getattr__动态拦截方法调用
Python对象模型里有个特殊方法__getattr__,当你访问对象上不存在的属性/方法时,它会自动触发。我们可以利用这个特性写一个通用包装类,把目标对象(比如Bravado生成的API客户端)传进去,所有方法调用都会被拦截,在包装逻辑里统一处理异常。
具体实现代码
先写通用的异常捕获包装器:
class ExceptionCatchingWrapper: def __init__(self, wrapped_obj, exception_handler=None): self.wrapped_obj = wrapped_obj # 支持自定义异常处理逻辑,默认打印异常信息 self.exception_handler = exception_handler or self.default_exception_handler def default_exception_handler(self, exc, method_name, args, kwargs): print(f"调用方法 {method_name} 时抛出异常: {type(exc).__name__}: {exc}") # 如果你需要让异常继续向上传播,取消下面的注释即可 # raise def __getattr__(self, name): # 获取原对象的属性或方法 attr = getattr(self.wrapped_obj, name) # 如果是可调用的方法,就给它套一层异常捕获的包装 if callable(attr): def wrapped_method(*args, **kwargs): try: return attr(*args, **kwargs) except Exception as exc: self.exception_handler(exc, name, args, kwargs) return wrapped_method # 如果是普通属性,直接返回原属性值 return attr
适配Bravado API测试的用法
假设你已经用Bravado生成了API客户端,直接用包装器包裹即可:
from bravado.client import SwaggerClient # 初始化Bravado客户端 client = SwaggerClient.from_url("http://your-api-docs-url/swagger.json") # 用包装器包裹客户端,自动捕获所有方法的异常 wrapped_client = ExceptionCatchingWrapper(client) # 正常调用API方法,非2xx状态码抛出的HTTPError会被自动捕获 wrapped_client.pet.getPetById(petId=123).response()
自定义Bravado专属异常处理
如果你需要针对Bravado的HTTPError(非2xx返回时抛出)做特殊处理,比如区分不同状态码的逻辑,可以自定义异常处理器:
from bravado.exception import HTTPError def bravado_custom_handler(exc, method_name, args, kwargs): if isinstance(exc, HTTPError): status_code = exc.response.status_code print(f"API调用 {method_name} 返回非2xx状态码: {status_code}") print(f"响应内容: {exc.response.text}") # 这里可以加业务逻辑:比如404标记测试跳过,500标记服务故障等 else: print(f"调用方法 {method_name} 时发生非API异常: {type(exc).__name__}: {exc}") # 用自定义处理器创建包装器 wrapped_client = ExceptionCatchingWrapper(client, exception_handler=bravado_custom_handler)
这个方案的优势
- 完全通用:不管目标对象有多少方法,都不用手动写包装代码,自动拦截所有调用
- 低侵入性:不用修改原对象的任何代码,只是做一层透明包装
- 灵活扩展:可以根据测试场景自定义异常处理,比如记录日志、标记测试结果、返回默认值等
内容的提问来源于stack exchange,提问作者Leandro Cofre
相关产品推荐
相关产品推荐

