5作者: lanemik大约 1 个月前原帖
我创建 Valid8r 是因为我厌倦了为每个 CLI 工具编写相同的输入验证代码。你知道这个模式:解析一个字符串,检查它是否有效,如果无效则打印错误,重新询问。对每个参数重复这个过程。 这个库使用 Maybe 单子(成功/失败而不是异常),因此你可以链式调用解析器和验证器: ```python # 尝试一下:pip install valid8r from valid8r.core import parsers, validators # 在一个管道中解析和验证 result = ( parsers.parse_int(user_input) .bind(validators.minimum(1)) .bind(validators.maximum(65535)) ) match result: case Success(port): print(f"使用端口 {port}") case Failure(error): print(f"无效: {error}") ``` 我为 argparse、Click 和 Typer 创建了集成,这样你就可以直接将 valid8r 解析器嵌入到现有的 CLI 中,而无需重构所有代码。 有趣的技术点是:在简单解析(整数、电子邮件、UUID)方面,它比 Pydantic 快 4-300 倍,因为它不构建模式或进行运行时类型检查。它仅解析字符串并返回 Maybe[T]。对于复杂的嵌套验证,Pydantic 仍然更好。我对两者进行了基准测试,并记录了各自的优劣。 我并不是想取代 Pydantic。如果你正在构建 FastAPI 服务,请使用 Pydantic。但如果你正在构建 CLI 工具或解析网络配置,Maybe 单子组合得非常好,并且保持你的代码功能性。 文档在 [https://valid8r.readthedocs.io/](https://valid8r.readthedocs.io/) ,基准测试在代码库中。它是 MIT 许可的。 非常希望能收到关于 API 设计的反馈。Maybe 单子模式对 Python 来说是否太奇怪,还是让验证代码更简洁? --- 这里有几个示例,展示了相同端口验证的不同语法选项: ```python from valid8r.core import parsers, validators # 选项 1:使用 & 运算符组合验证器 validator = validators.minimum(1) & validators.maximum(65535) result = parsers.parse_int(user_input).bind(validator) # 选项 2:使用 parse_int_with_validation(内置) result = parsers.parse_int_with_validation( user_input, validators.minimum(1) & validators.maximum(65535) ) # 选项 3:交互式提示(持续询问直到有效) from valid8r.prompt import ask port = ask( "请输入端口号(1-65535):", parser=lambda s: parsers.parse_int(s).bind( validators.minimum(1) & validators.maximum(65535) ) ) # 这里 port 保证有效,无需匹配 # 选项 4:创建可重用的解析器函数 def parse_port(text): return parsers.parse_int(text).bind( validators.minimum(1) & validators.maximum(65535) ) result = parse_port(user_input) ``` & 运算符可能是组合验证器最简洁的方式。交互式提示也很好,因为你不需要匹配成功/失败,它会不断循环,直到用户提供有效输入。