Python 中的参数验证

问题描述 投票:0回答:2

我有一个函数接受一些需要验证的参数。例如:

def foo(a: int, b: float, c: str) -> None:
    if a <= 0:
        raise ValueError(f"'a' must pe positive: {a}")
    if not (0 < b <= 1):
        raise ValueError(f"'b' must be in the range (0, 1]: {b}")
    if not c:
        raise ValueError(f"'c' can't be empty: {c!r}")
    # Do things with the validated parameters a, b and c...

这是很多样板代码,用于在我到达函数的实际代码之前验证参数。我想知道是否有一个方案或一个库来简化此参数验证。我将

attrs
及其验证器用于类的字段,但它不适用于简单的函数。我尝试了
validate_call
中的
pydantic
装饰器,但问题是
pydantic
看起来像是一个“全集成”库。我必须验证所有内容,如果我有一些不需要验证的参数,或者我认为类型提示和静态检查足够好,那么
pydantic
仍然尝试验证它们,这很糟糕,尤其是当我有复杂的情况时任意类型的类型提示,例如
Callable
numpy
数组(我知道
arbitrary_types_allowed
参数,但它仍然执行
isinstance
检查,在我看来这是浪费)。

换句话说,我真的不需要像

pydantic
这样复杂的数据验证解决方案。我只需要添加简单的验证当我想要的时候。我想要类似
attrs
的东西,其中验证是可选的(如果我声明
attrs
字段并传递给它一个字符串,
int
不会抱怨。只有静态类型检查器会警告我),并且如果我想要例如,为了确保
int
字段为正,我可以轻松添加一个没有样板的验证器。我想要类似的函数及其参数。我应该使用哪个库来实现如此简单的函数验证?

python validation
2个回答
0
投票

我用

marshmallow
来存放我的东西。您可以尝试以下方法是否适合您:

from functools import wraps 
from marshmallow import Schema, fields, validate  
  
class FooArgsSchema(Schema):  
    a = fields.Int(required=True, validate=validate.Range(min=1))  
    b = fields.Float(required=True, validate=validate.Range(min=0, max=1, min_inclusive=False))  
    c = fields.Str(required=True, validate=validate.Length(min=1))  
  
def validate_args(schema):  
    def decorator(func):  
        @wraps(func)  
        def wrapper(*args, **kwargs):  
            data = schema().load(kwargs)  
            return func(**data)  
        return wrapper  
    return decorator  

@validate_args(FooArgsSchema)  
def foo(a: int, b: float, c: str) -> None:  
    # Do things with the validated parameters a, b, and c...  
    print(f"a: {a}, b: {b}, c: {c}")  
  
# Test the function  
foo(a=1, b=0.5, c="hello")  # Valid input  
foo(a=0, b=0.5, c="hello")  # Raises a ValidationError

-1
投票

那么,您是否考虑过编写另一个函数,只负责验证?

def validateParams():
          #Do the necessary validation
def foo():
    validateParams()
© www.soinside.com 2019 - 2024. All rights reserved.