我想使用argparse来解析布尔命令行参数写为“——foo True”或“——foo False”。例如:
my_program --my_boolean_flag False
然而,下面的测试代码并没有做我想要的:
import argparse
parser = argparse.ArgumentParser(description="My parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)
可悲的是,parsed_args。my_bool的值为True。即使我将cmd_line更改为["——my_bool", ""],这也是如此,这是令人惊讶的,因为bool("")的值为False。
我怎么能得到argparse解析“假”,“F”,和他们的小写变体为假?
转换值:
def __arg_to_bool__(arg):
"""__arg_to_bool__
Convert string / int arg to bool
:param arg: argument to be converted
:type arg: str or int
:return: converted arg
:rtype: bool
"""
str_true_values = (
'1',
'ENABLED',
'ON',
'TRUE',
'YES',
)
str_false_values = (
'0',
'DISABLED',
'OFF',
'FALSE',
'NO',
)
if isinstance(arg, str):
arg = arg.upper()
if arg in str_true_values:
return True
elif arg in str_false_values:
return False
if isinstance(arg, int):
if arg == 1:
return True
elif arg == 0:
return False
if isinstance(arg, bool):
return arg
# if any other value not covered above, consider argument as False
# or you could just raise and error
return False
[...]
args = ap.parse_args()
my_arg = options.my_arg
my_arg = __arg_to_bool__(my_arg)
这其实已经过时了。对于Python 3.7+, Argparse现在支持布尔参数(search BooleanOptionalAction)。
实现如下所示:
import argparse
ap = argparse.ArgumentParser()
# List of args
ap.add_argument('--foo', default=True, type=bool, help='Some helpful text that is not bar. Default = True')
# Importable object
args = ap.parse_args()
还有一件事需要提到:这将阻塞通过argparse.ArgumentTypeError参数的除True和False以外的所有条目。如果您出于任何原因想要尝试更改它,您可以为此创建一个自定义错误类。
我认为更规范的做法是:
command --feature
and
command --no-feature
Argparse很好地支持这个版本:
Python 3.9 +:
parser.add_argument('--feature', action=argparse.BooleanOptionalAction)
Python < 3.9:
parser.add_argument('--feature', action='store_true')
parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)
当然,如果你真的想要——arg <True|False>版本,你可以传递ast.literal_eval作为“类型”,或者一个用户定义的函数…
def t_or_f(arg):
ua = str(arg).upper()
if 'TRUE'.startswith(ua):
return True
elif 'FALSE'.startswith(ua):
return False
else:
pass #error condition maybe?