我想使用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”,和他们的小写变体为假?
这其实已经过时了。对于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以外的所有条目。如果您出于任何原因想要尝试更改它,您可以为此创建一个自定义错误类。
这适用于我所期望的一切:
add_boolean_argument(parser, 'foo', default=True)
parser.parse_args([]) # Whatever the default was
parser.parse_args(['--foo']) # True
parser.parse_args(['--nofoo']) # False
parser.parse_args(['--foo=true']) # True
parser.parse_args(['--foo=false']) # False
parser.parse_args(['--foo', '--nofoo']) # Error
代码:
def _str_to_bool(s):
"""Convert string to bool (in argparse context)."""
if s.lower() not in ['true', 'false']:
raise ValueError('Need bool; got %r' % s)
return {'true': True, 'false': False}[s.lower()]
def add_boolean_argument(parser, name, default=False):
"""Add a boolean argument to an ArgumentParser instance."""
group = parser.add_mutually_exclusive_group()
group.add_argument(
'--' + name, nargs='?', default=default, const=True, type=_str_to_bool)
group.add_argument('--no' + name, dest=name, action='store_false')
您可以创建一个BoolAction,然后使用它
class BoolAction(Action):
def __init__(
self,
option_strings,
dest,
nargs=None,
default: bool = False,
**kwargs,
):
if nargs is not None:
raise ValueError('nargs not allowed')
super().__init__(option_strings, dest, default=default, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
input_value = values.lower()
b = input_value in ['true', 'yes', '1']
if not b and input_value not in ['false', 'no', '0']:
raise ValueError('Invalid boolean value "%s".)
setattr(namespace, self.dest, b)
然后在parser.add_argument()中设置action=BoolAction
这其实已经过时了。对于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以外的所有条目。如果您出于任何原因想要尝试更改它,您可以为此创建一个自定义错误类。
在之前跟随@akash-desarda的优秀回答https://stackoverflow.com/a/59579733/315112后,通过lambda使用strtobool,后来,我决定直接使用strtobool。
import argparse
from distutils import util
parser.add_argument('--feature', type=util.strtobool)
是的,你是对的,strtobool返回的是int型,而不是bool型。但是strtobool将不会返回除0和1之外的任何其他值,而python将无缝一致地将它们转换为bool值。
>>> 0 == False
True
>>> 0 == True
False
>>> 1 == False
False
>>> 1 == True
True
当接收到错误的输入值时
python yours.py --feature wrong_value
一个argparse。与lambda相比,使用strtoool的Action将产生一个稍微清晰/可理解的错误消息:
yours.py: error: argument --feature: invalid strtobool value: 'wrong_value'
与此代码相比,
parser.add_argument('--feature', type=lambda x: bool(util.strtobool(x))
这将产生一个不太清楚的错误消息:
yours.py: error: argument --feature: invalid <lambda> value: 'wrong_value'