5作者: lanemik7 个月前
我构建 Valid8r 是因为我厌倦了为每个 CLI 工具编写相同的输入验证代码。你懂的,就是那个模式:解析一个字符串,检查它是否有效,如果无效就打印错误,然后重新提问。对每个参数都重复这个过程。 这个库使用 Maybe monad(Success/Failure 而不是异常),所以你可以链式调用解析器和验证器: ```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 monad 的组合效果非常好,并且能让你的代码保持函数式。 文档位于 <https://valid8r.readthedocs.io/>,基准测试在仓库中。它采用 MIT 许可证。 很想听听关于 API 设计的反馈。Maybe monad 模式对 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) ``` 对于组合验证器来说,& 运算符可能是最简洁的。交互式提示也很棒,因为你不需要匹配 Success/Failure,它会一直循环直到用户提供有效输入。