如何从 Pydantic 模型创建参数解析器 (
argparse.ArgumentParser
)?
我有一个 Pydantic 模型:
from pydantic import BaseModel, Field
class MyItem(BaseModel):
name: str
age: int
color: str = Field(default="red", description="Color of the item")
我想使用命令行创建
MyItem
的实例:
python myscript.py --name Jack --age 10 --color blue
这应该产生:
item = MyItem(name="Jack", age=10, color="blue")
... # Process the item
我不想对命令行参数进行硬编码,我想从 Pydantic 模型动态创建命令行参数。
我自己找到了答案。只是:
import argparse
from pydantic import BaseModel, Field
class MyItem(BaseModel):
name: str
age: int
color: str = Field(default="red", description="Color of the item")
def add_model(parser, model):
"Add Pydantic model to an ArgumentParser"
fields = model.__fields__
for name, field in fields.items():
parser.add_argument(
f"--{name}",
dest=name,
type=field.type_,
default=field.default,
help=field.field_info.description,
)
# 1. Create and parse command line arguments
parser = argparse.ArgumentParser()
# 2. Turn the fields of the model as arguments of the parser
add_model(parser, MyItem)
# 3. Parse the command-line arguments
args = parser.parse_args()
# 4. Turn the arguments as dict and pass them to the model
item = MyItem(**vars(args))
# 5. Do whatever
print(repr(item))
...
如果您希望向解析器添加更多功能,也可以添加子解析器:https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_subparsers
有一个名为 pydantic-argparse 的库,它可能可以满足您的需要,无需额外的样板代码。
这是其文档中的示例
import pydantic
import pydantic_argparse
class Arguments(pydantic.BaseModel):
# Required Args
string: str = pydantic.Field(description="a required string")
integer: int = pydantic.Field(description="a required integer")
flag: bool = pydantic.Field(description="a required flag")
# Optional Args
second_flag: bool = pydantic.Field(False, description="an optional flag")
third_flag: bool = pydantic.Field(True, description="an optional flag")
def main() -> None:
# Create Parser and Parse Args
parser = pydantic_argparse.ArgumentParser(
model=Arguments,
prog="Example Program",
description="Example Description",
version="0.0.1",
epilog="Example Epilog",
)
args = parser.parse_typed_args()
# Print Args
print(args)
if __name__ == "__main__":
main()