使用argparse解析布尔值
我想用 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 把 "False"
、"F"
以及它们的小写形式解析为 False
呢?
28 个回答
506
这是另一个使用之前建议的解决方案,但这次能正确处理来自 argparse
的解析错误:
def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')
这对于创建带有默认值的开关非常有用;比如说:
parser.add_argument("--nice", type=str2bool, nargs='?',
const=True, default=False,
help="Activate nice mode.")
让我可以使用:
script --nice
script --nice <bool>
并且仍然可以使用一个默认值(特定于用户设置)。不过,这种方法有一个(间接相关的)缺点,就是 'nargs' 可能会捕获一个位置参数——可以查看 这个相关问题 和 这个 argparse 的错误报告。
1484
我觉得更标准的做法是通过以下方式来实现:
command --feature
还有
command --no-feature
argparse
在这个版本中支持得很好:
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?
40
最简单也是最正确的方法是:
from distutils.util import strtobool
parser.add_argument('--feature', dest='feature',
type=lambda x: bool(strtobool(x)))
请注意,代表“真”的值有 y、yes、t、true、on 和 1;而代表“假”的值有 n、no、f、false、off 和 0。如果输入的值不在这些范围内,就会出现一个叫做 ValueError 的错误。