如何复用Azure Functions中带提前返回的try...except代码块?
问题
正在编写Azure Functions API,拥有多个内部逻辑相似的端点。每个端点的核心步骤是将原始POST请求的参数字典解析为自定义请求对象,该对象会校验必填参数:缺失参数时抛出KeyError,参数不合法时抛出ValueError,触发主函数提前返回错误响应。目前每个端点函数都需要重复编写相同的try...except块,能否将该逻辑抽象为可复用模块?
端点示例代码
from requests import ShowUsersRequest import azure.functions as func def my_endpoint(req: azure.functions.HttpRequest): try: wrapped_request = ShowUsersRequest(req) except KeyError: return func.HttpResponse('Request missing argument(s)', status_code=400) except ValueError as e: return func.HttpResponse(f'One or more request arguments was of invalid type. {e.args[0]}', status_code=400) # ... 后续业务逻辑
自定义请求对象示例代码
# requests.py import azure.functions as func class ShowUsersRequest: def __init__(self, req: func.HttpRequest) -> None: # 缺少参数键时会抛出KeyError self.identifier = req.params['account_identifier'] self.client_code = int(req.params['client_code']) # 参数不合法时抛出ValueError if self.client_code < 0: raise ValueError('Client code must be non-negative')
解决方案
当然可以,最简洁高效的方式是使用Python装饰器封装重复的错误处理逻辑,无需在每个端点函数中重复编写try...except块。
1. 编写通用请求校验装饰器
创建decorators.py模块,把错误捕获和响应逻辑封装成可复用的装饰器:
import azure.functions as func from functools import wraps def validate_request(request_cls): """ 装饰器:自动解析并校验请求参数,捕获KeyError和ValueError并返回标准错误响应 :param request_cls: 自定义请求对象类 """ def decorator(endpoint_func): @wraps(endpoint_func) def wrapper(req: func.HttpRequest): try: # 实例化自定义请求对象,自动完成参数校验 wrapped_request = request_cls(req) except KeyError: return func.HttpResponse('请求缺少必要参数', status_code=400) except ValueError as e: return func.HttpResponse(f'请求参数不合法:{str(e)}', status_code=400) # 校验通过后,将封装好的请求对象传入原端点函数 return endpoint_func(req, wrapped_request) return wrapper return decorator
2. 改造端点函数
在端点函数上添加装饰器,直接使用校验后的请求对象,无需再处理错误逻辑:
from requests import ShowUsersRequest from decorators import validate_request import azure.functions as func @validate_request(ShowUsersRequest) def my_endpoint(req: func.HttpRequest, wrapped_request: ShowUsersRequest): # 直接使用已校验的wrapped_request对象 print(f"处理账号:{wrapped_request.identifier},客户端代码:{wrapped_request.client_code}") # ... 执行后续业务逻辑 return func.HttpResponse('请求处理成功', status_code=200)
可选优化:统一请求基类
如果需要进一步复用请求对象的通用逻辑(比如统一获取JSON/表单参数),可以创建基类,但这不会替代装饰器的错误处理作用:
# requests.py import azure.functions as func class BaseRequest: def __init__(self, req: func.HttpRequest): self.req = req # 统一获取参数(支持GET params或POST表单/JSON) self.params = req.params or req.get_json() or {} self._parse_and_validate() def _parse_and_validate(self): # 子类需实现该方法完成具体参数解析 raise NotImplementedError class ShowUsersRequest(BaseRequest): def _parse_and_validate(self): self.identifier = self.params['account_identifier'] self.client_code = int(self.params['client_code']) if self.client_code < 0: raise ValueError('客户端代码不能为负数')
内容的提问来源于stack exchange,提问作者walkrflocka
相关产品推荐
相关产品推荐

