Python Argparse可选布尔值
我试图获得以下行为:Python Argparse可选布尔值,python,python-3.x,argparse,Python,Python 3.x,Argparse,我试图获得以下行为: python test.py=>store foo=False python test.py--foo=>store foo=True python test.py--foo bool=>store foo=bool 当我使用 parser.add_argument('--foo',nargs='?', default=False, const=True) 但是,如果我添加type=bool,试图强制强制强制转换为布尔值,它就会中断。在这种情况下 python
- python test.py=>store foo=False
- python test.py--foo=>store foo=True
- python test.py--foo bool=>store foo=bool
parser.add_argument('--foo',nargs='?', default=False, const=True)
但是,如果我添加type=bool
,试图强制强制强制转换为布尔值,它就会中断。在这种情况下
python test.py --foo False
实际上最终存储的是foo=True
。发生了什么事???您应该将参数改为布尔参数:
parser.add_argument('--foo', action='store_true')
因此,如果没有--foo
选项:
python test.py
python test.py --foo
将导致foo
参数的False
值,并且存在--foo
选项:
python test.py
python test.py --foo
将导致foo
参数的True
值。您确定需要该模式吗--foo
和--foo
组合在一起,对于布尔开关来说,不是一种常用的模式
至于您的问题,请记住命令行值是一个字符串,type=bool
表示您希望应用bool(输入的字符串值)
。对于——foo False
,这意味着bool(“False”)
,产生True
;所有非空字符串都为真!我也看到了
与其支持--foo
/--foo
,我强烈建议您使用--foo
表示真
,删除参数值,而是添加--no foo
选项以显式设置假
:
parser.add_argument('--foo', default=False, action='store_true')
parser.add_argument('--no-foo', dest='foo', action='store_false')
--no foo
开关上添加的dest='foo'
确保它存储的False
值(通过store\u False
)最终位于相同的args.foo
属性上
从Python 3.9开始,您还可以使用argparse.BooleanOptionalAction
action类:
parser.add_argument("--foo", action=argparse.BooleanOptionalAction)
它将具有相同的效果,处理--foo
和--no foo
来设置和清除标志
如果您有一些其他配置机制将foo
设置为True
,并且需要使用命令行开关再次覆盖,那么您只需要一个--foo/--no foo
组合--no-
是一种广泛采用的标准,用于反转布尔命令行开关
如果您不需要使用--no-foo
反向开关(因为省略--foo
已经意味着“false”),那么只需使用操作class='store\u true'
选项即可。这使您的命令行简单明了
但是,如果您的用例或其他约束特别要求您的命令行必须具有某种对--foo(true | false | 0 | 1)
的支持,那么添加您自己的转换器:
def str_to_bool(value):
if isinstance(value, bool):
return value
if value.lower() in {'false', 'f', '0', 'no', 'n'}:
return False
elif value.lower() in {'true', 't', '1', 'yes', 'y'}:
return True
raise ValueError(f'{value} is not a valid boolean value')
parser.add_argument('--foo', type=str_to_bool, nargs='?', const=True, default=False)
值用于省略参数值的const
参数。在这里,当使用nargs='?'
时,设置--foo
foo=True
- 当根本不使用开关时,将使用
default=False
用于处理type=str\u to\u bool
案例--foo
但这不允许使用
--foo bool
。这是不需要的。我已经用更好的解释更新了我的答案。当然,但是有指定禁用foo选项的用例,特别是在“来自多个源的合并配置,包括命令行”场景中<代码>--no foo是这里的常见选择。另外,我之所以要这样做,是因为我正在编写的是一个构建器文件,它编写了大量bash脚本并将它们提交给SLURM工作负载管理器。我提交的可选参数要经过一些预处理步骤,然后在SLURM脚本内的python调用中附加一组派生参数。现在,我发现实现这一点的最简单方法是拥有一个参数字典,我希望将其传递给SLURM脚本并附加所有键值对。现在根据您的建议,我必须检查是否手动设置了一个标志。@Hyperplane:您可以接受JSON编码的配置字符串吗?然后,如果args.json\u config
是解码的json对象,那么您所要做的就是使用args=parser.parse\u args()
和args.update(args.json\u config)
@Hyperplane:parser.add\u参数('--json config',type=json.loads)
应该足以定义这样一个开关。这听起来是一个非常好的解决方案。目前使用type=string2bool
似乎已经足够了,但我会记住这个想法。再次感谢您的--no-pattern,argparse引入了BooleanOptionalAction