Pydantic 模型的参数解析器

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

如何从 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 模型动态创建命令行参数。

python argparse pydantic
2个回答
9
投票

我自己找到了答案。只是:

  1. 创建一个参数解析器,
  2. 将模型的字段作为解析器的参数,
  3. 解析命令行参数,
  4. 将参数转换为 dict 并将它们传递给模型并且
  5. 处理模型实例
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


0
投票

有一个名为 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()

© www.soinside.com 2019 - 2024. All rights reserved.