通常,我们在开发Web应用时,会使用jsonschema对Request入参进行校验。
那么如果仅是常规的Python函数,又该如何进行校验。
我们希望能够做到:
对业务代码侵入性小; 校验代码与业务代码通过约定进行匹配,可以独立调整; 代码阅读流畅。自然地我想到使用Python的装饰器来实现。
先放出装饰器代码
#!/usr/bin/python # -*- coding: UTF-8 -*- import functools import inspect from typing import Callable from jsonschema import validate, exceptions def validated(validator, role: str = 'FUNC'): def decorator(func: Callable): @functools.wraps(func) def wrapper(*args, **kwargs): args_spec = inspect.getfullargspec(func) instance = (args_spec.kwonlydefaults or {}).copy() # 取func定义的缺省值 instance.update(kwargs) # 使用实际的kw参数更新默认值(如果有的话) if args_spec.args is not None: # 更新实际传入的args instance.update({arg_name: args[index] for index, arg_name in enumerate(args_spec.args) if arg_name != 'self'}) schema = validator.get_schema(role=role) schema['additionalProperties'] = True try: validate(instance, schema) except exceptions.ValidationError as ex: arg_name = ex.relative_path[-1] raise ValueError('Parameter {0!r} - {1}'.format(arg_name, ex.message)) from None else: return func(*args, **kwargs) return wrapper return decorator
代码逻辑说明:
通过inspect获取函数的反射信息 尝试构造一个待审查的json实例instance 2.1 instance初始化为func的缺省参数(带参数值) 2.2 使用调用func时的实际关键字参数kwargs更新instance 2.3 如果func存在args,使用func中定义的{参数名:实际参数值}更新instance 从装饰器传入的validator(这里采用jsl包中的jsl.Document)取出校验schma 使用jsonschema.validate执行校验,成功的话执行原func,否则抛出首个不匹配的参数及错误详情来一个简单的使用代码示例:
# schema.py ... class CreateAccountOfKeyPairSchema(Document): app = StringField(required=True, pattern=r'^[^!#$%&*,]*$') subject = StringField(required=True, pattern=r'^[^!#$%&*,]*$') custom = StringField(required=True, pattern=r'^[^!#$%&*,]*$') data = StringField(required=False) ... # service.py ... @validated(CreateAccountOfKeyPairSchema) def create_account(self, app: str, subject: str, custom: str, data: str) -> str: biz = TenAccountInfo() biz.id = self._account_info_id_generator.next() biz.app = app biz.subject = subject biz.custom = custom biz.data = data biz.invalid = 0 biz.version = self._version_generator.next() ret = biz.id self._account_info_dao.save(biz) return ret ...
查看更多关于使用jsonschema通过装饰器优雅地对Python函数参数进行校验的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did126322