使用 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_boolTruecmd_line["--my_bool", ""]bool("")False

如何让 argparse 解析 、 和它们的小写变体?"False""F"False


答案 1

我认为一个更规范的方法是通过:

command --feature

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?

答案 2

这是另一个使用上述建议的解决方案,但带有来自以下的“正确”解析错误: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错误报告