Python+Typer中带整数值Enum如何自动支持字符串命令行参数?
在Typer中使用带整数值的Enum作为命令行参数的解决方案
问题背景
使用Python 3.8.10搭配Typer 0.7.0时,希望将带整数值的Enum类作为命令行输入参数。此前在argparse中,通过设置choices=list(ModelTypeEnum)并给Enum重写__str__返回枚举名,可以正常支持输入枚举名作为参数:
from enum import Enum class ModelTypeEnum(Enum): ALEXNET = 0 RESNET50 = 1 VGG19 = 2 def __str__(self): return self.name
但直接在Typer中使用该Enum作为参数类型时,命令行输入枚举名字符串(如RESNET50)会触发错误:
click.exceptions.BadParameter: 'RESNET50' is not one of 0, 1, 2.
Typer默认只接受枚举对应的整数值输入,需要保留Enum的整数值,同时支持输入枚举名,且不想将Enum改为字符串类型。
可行方案
方案1:自定义参数解析器
如果无法修改现有Enum的继承关系,可以通过自定义解析函数,让Typer同时支持枚举名和整数值输入:
from enum import Enum import typer from click import BadParameter class ModelTypeEnum(Enum): ALEXNET = 0 RESNET50 = 1 VGG19 = 2 def __str__(self): return self.name def parse_model_type(value: str) -> ModelTypeEnum: # 优先匹配枚举名(忽略大小写) try: return ModelTypeEnum[value.upper()] except KeyError: # 匹配失败则尝试转换为整数匹配枚举值 try: return ModelTypeEnum(int(value)) except ValueError: valid_options = [f"{e.name}({e.value})" for e in ModelTypeEnum] raise BadParameter(f"无效的模型类型,可选值:{', '.join(valid_options)}") app = typer.Typer() @app.command() def main( model_type: ModelTypeEnum = typer.Argument(..., help="选择模型", parser=parse_model_type) ): print(f"选中模型:{model_type.name},对应值:{model_type.value}") return 0 if __name__ == "__main__": app()
这个解析函数会先尝试将输入字符串转为大写后匹配枚举名,失败则转为整数匹配枚举值,两种输入方式均支持,同时保留Enum的整数值。
方案2:使用Typer官方Enum类(推荐)
Typer提供了typer.Enum类,它是标准库Enum的子类,专门适配Typer/Click的参数解析逻辑,默认支持同时通过枚举名和整数值输入:
import typer class ModelTypeEnum(typer.Enum): ALEXNET = 0 RESNET50 = 1 VGG19 = 2 app = typer.Typer() @app.command() def main(model_type: ModelTypeEnum = typer.Argument(..., help="选择模型")): print(f"选中模型:{model_type.name},对应值:{model_type.value}") return 0 if __name__ == "__main__": app()
这种方式无需自定义解析逻辑,代码更简洁,是Typer官方推荐的Enum适配方案,完全满足保留整数值、支持枚举名输入的需求。
内容的提问来源于stack exchange,提问作者AdmiralJonB
相关产品推荐
相关产品推荐

