问题:用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
什么?
回答 0
另一个解决方案使用了先前的建议,但存在来自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>
并仍使用默认值(特定于用户设置)。这种方法的一个(间接相关的)缺点是“水罐”可能会引起位置争执-请参阅此相关问题和此argparse错误报告。
回答 1
我认为更规范的方法是通过:
command --feature
和
command --no-feature
argparse
很好地支持此版本:
parser.add_argument('--feature', dest='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
我建议mgilson的答案,但有互相排斥的群体
,这样就可以不使用--feature
,并--no-feature
在同一时间。
command --feature
和
command --no-feature
但不是
command --feature --no-feature
脚本:
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')
回答 3
这是另一种变体,无需额外的行来设置默认值。布尔值始终分配有一个值,以便可以在逻辑语句中使用它而无需预先检查。
import argparse
parser = argparse.ArgumentParser(description="Parse bool")
parser.add_argument("--do-something", default=False, action="store_true" , help="Flag to do something")
args = parser.parse_args()
if args.do_something:
print("Do something")
else:
print("Don't do something")
print("Check that args.do_something=" + str(args.do_something) + " is always a bool")
回答 4
单线:
parser.add_argument('--is_debug', default=False, type=lambda x: (str(x).lower() == 'true'))
回答 5
关于什么type=bool
以及type='bool'
可能意味着什么似乎有些困惑。一个(或两个)是否应该表示“运行函数bool()
或”返回布尔值”?就目前而言,它type='bool'
毫无意义。 add_argument
给出'bool' is not callable
错误,与您使用type='foobar'
或相同type='int'
。
但是argparse
确实有注册表可以让您定义这样的关键字。它主要用于action
,例如`action =’store_true’。您可以通过以下方式查看已注册的关键字:
parser._registries
显示字典
{'action': {None: argparse._StoreAction,
'append': argparse._AppendAction,
'append_const': argparse._AppendConstAction,
...
'type': {None: <function argparse.identity>}}
定义了许多动作,但只有一种类型,默认类型为argparse.identity
。
这段代码定义了一个’bool’关键字:
def str2bool(v):
#susendberg's function
return v.lower() in ("yes", "true", "t", "1")
p = argparse.ArgumentParser()
p.register('type','bool',str2bool) # add type keyword to registries
p.add_argument('-b',type='bool') # do not use 'type=bool'
# p.add_argument('-b',type=str2bool) # works just as well
p.parse_args('-b false'.split())
Namespace(b=False)
parser.register()
没有记录,但也没有隐藏。在大多数情况下,程序员并不需要了解它,因为type
和action
取函数和类值。有很多为这两者定义自定义值的stackoverflow示例。
万一从前面的讨论中看bool()
不出来,就不意味着“解析字符串”。从Python文档中:
bool(x):使用标准真值测试过程将值转换为布尔值。
与之对比
int(x):将数字或字符串x转换为整数。
回答 6
我一直在寻找相同的问题,恕我直言,漂亮的解决方案是:
def str2bool(v):
return v.lower() in ("yes", "true", "t", "1")
并按照上面的建议使用它来将字符串解析为布尔值。
回答 7
一个非常类似的方法是使用:
feature.add_argument('--feature',action='store_true')
如果您在命令中设置了参数–feature
command --feature
如果未设置type –feature,则参数将为True,参数默认始终为False!
回答 8
除了@mgilson所说的以外,还应注意还有一种ArgumentParser.add_mutually_exclusive_group(required=False)
方法可以使执行该操作变得微不足道,--flag
并且--no-flag
不能同时使用。
回答 9
这适用于我期望的所有功能:
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')
回答 10
一种更简单的方法是按以下方式使用。
parser.add_argument('--feature', type=lambda s: s.lower() in ['true', 't', 'yes', '1'])
回答 11
最简单 它不灵活,但我更喜欢简单。
parser.add_argument('--boolean_flag',
help='This is a boolean flag.',
type=eval,
choices=[True, False],
default='True')
编辑:如果您不信任输入,请不要使用eval
。
回答 12
最简单的方法是使用选择:
parser = argparse.ArgumentParser()
parser.add_argument('--my-flag',choices=('True','False'))
args = parser.parse_args()
flag = args.my_flag == 'True'
print(flag)
不通过–my-flag评估为False。该要求=真,如果你总是希望用户显式地指定一个选择的选项可以添加。
回答 13
我认为最典型的方法是:
parser.add_argument('--ensure', nargs='*', default=None)
ENSURE = config.ensure is None
回答 14
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)
回答 15
最简单,最正确的方法是
from distutils import util
arser.add_argument('--feature', dest='feature', type=lambda x:bool(distutils.util.strtobool(x)))
请注意,True值为y,y,t,true,on和1;false值是n,no,f,false,off和0。如果val是其他值,则引发ValueError。
回答 16
快速简便,但仅适用于参数0或1:
parser.add_argument("mybool", default=True,type=lambda x: bool(int(x)))
myargs=parser.parse_args()
print(myargs.mybool)
从终端调用后,输出将为“ False”:
python myscript.py 0
回答 17
类似于@Akash,但这是我使用的另一种方法。它之所以有用str
,lambda
是因为python lambda
总是给我一种外星人的感觉。
import argparse
from distutils.util import strtobool
parser = argparse.ArgumentParser()
parser.add_argument("--my_bool", type=str, default="False")
args = parser.parse_args()
if bool(strtobool(args.my_bool)) is True:
print("OK")
回答 18
为了改善@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