我想使用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”,和他们的小写变体为假?


当前回答

只要执行以下操作,就可以使用——test = True

Python文件名——test

parser.add_argument("--test" , default=False ,help="test ?", dest='test', action='store_true')

其他回答

扩展杰拉德的回答

原因解析器。add_argument("——my_bool", type=bool)不起作用,因为bool("mystring")对于任何非空字符串都是True,所以bool("False")实际上是True。

你想要的是

my_program.py

import argparse

parser = argparse.ArgumentParser(description="My parser")

parser.add_argument(
        "--my_bool",
        choices=["False", "True"],
        )

parsed_args = parser.parse_args()

my_bool = parsed_args.my_bool == "True"

print(my_bool)
$ python my_program.py --my_bool False
False

$ python my_program.py --my_bool True
True

$ python my_program.py --my_bool true
usage: my_program.py [-h] [--my_bool {False,True}]
my_program.py: error: argument --my_bool: invalid choice: 'true' (choose from 'False', 'True')

如果你想同时允许——特征和——无特征(最后一个胜出)

这允许用户使用——feature创建shell别名,并使用——no-feature覆盖它。

Python 3.9及以上版本

parser.add_argument('--feature', default=True, action=argparse.BooleanOptionalAction)

Python 3.8及以下版本

我推荐mgilson的回答:

parser.add_argument('--feature', dest='feature', action='store_true')
parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

如果你不想同时允许—功能和—无功能

你可以使用互斥组:

feature_parser = parser.add_mutually_exclusive_group(required=False)
feature_parser.add_argument('--feature', dest='feature', action='store_true')
feature_parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

你可以使用这个帮助器,如果你要设置很多:

def add_bool_arg(parser, name, default=False):
    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--' + name, dest=name, action='store_true')
    group.add_argument('--no-' + name, dest=name, action='store_false')
    parser.set_defaults(**{name:default})

add_bool_arg(parser, 'useful-feature')
add_bool_arg(parser, 'even-more-useful-feature')
class FlagAction(argparse.Action):
    # From http://bugs.python.org/issue8538

    def __init__(self, option_strings, dest, default=None,
                 required=False, help=None, metavar=None,
                 positive_prefixes=['--'], negative_prefixes=['--no-']):
        self.positive_strings = set()
        self.negative_strings = set()
        for string in option_strings:
            assert re.match(r'--[A-z]+', string)
            suffix = string[2:]
            for positive_prefix in positive_prefixes:
                self.positive_strings.add(positive_prefix + suffix)
            for negative_prefix in negative_prefixes:
                self.negative_strings.add(negative_prefix + suffix)
        strings = list(self.positive_strings | self.negative_strings)
        super(FlagAction, self).__init__(option_strings=strings, dest=dest,
                                         nargs=0, const=None, default=default, type=bool, choices=None,
                                         required=required, help=help, metavar=metavar)

    def __call__(self, parser, namespace, values, option_string=None):
        if option_string in self.positive_strings:
            setattr(namespace, self.dest, True)
        else:
            setattr(namespace, self.dest, False)

一个更简单的方法是使用如下所示。

parser.add_argument('--feature', type=lambda s: s.lower() in ['true', 't', 'yes', '1'])

作为对@Akash Desarda的回答的改进,你可以这样做

import argparse
from distutils.util import strtobool

parser = argparse.ArgumentParser()
parser.add_argument("--foo", 
    type=lambda x:bool(strtobool(x)),
    nargs='?', const=True, default=False)
args = parser.parse_args()
print(args.foo)

它支持python test.py——foo

(base) [costa@costa-pc code]$ python test.py
False
(base) [costa@costa-pc code]$ python test.py --foo 
True
(base) [costa@costa-pc code]$ python test.py --foo True
True
(base) [costa@costa-pc code]$ python test.py --foo False
False