Sup*_*ric 532 python boolean command-line-parsing argparse
我想使用argparse来解析写为"--foo True"或"--foo False"的布尔命令行参数.例如:
my_program --my_boolean_flag False
Run Code Online (Sandbox Code Playgroud)
但是,以下测试代码不能满足我的要求:
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)
Run Code Online (Sandbox Code Playgroud)
可悲的是,parsed_args.my_bool评估为True.这种情况即使我改变cmd_line为["--my_bool", ""],这是令人惊讶的,因为bool("")重新评估False.
如何让argparse解析"False","F"以及它们的小写变体False?
mgi*_*son 778
我认为一个更规范的方法是通过:
command --feature
Run Code Online (Sandbox Code Playgroud)
和
command --no-feature
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
当然,如果你真的想要--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?
Run Code Online (Sandbox Code Playgroud)
Max*_*xim 218
使用之前建议的另一种解决方案,但具有"正确"解析错误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.')
Run Code Online (Sandbox Code Playgroud)
这对于使用默认值制作开关非常有用; 例如
parser.add_argument("--nice", type=str2bool, nargs='?',
const=True, default=False,
help="Activate nice mode.")
Run Code Online (Sandbox Code Playgroud)
允许我使用:
script --nice
script --nice <bool>
Run Code Online (Sandbox Code Playgroud)
并仍然使用默认值(特定于用户设置).这种方法的一个(间接相关的)缺点是'nargs'可能会捕获位置参数 - 请参阅此相关问题和这个argparse错误报告.
fnk*_*nkr 215
我建议mgilson的答案,但有互相排斥的群体
,这样就可以不使用--feature,并--no-feature在同一时间.
command --feature
Run Code Online (Sandbox Code Playgroud)
和
command --no-feature
Run Code Online (Sandbox Code Playgroud)
但不是
command --feature --no-feature
Run Code Online (Sandbox Code Playgroud)
脚本:
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)
Run Code Online (Sandbox Code Playgroud)
如果要设置其中许多帮助,则可以使用此帮助程序:
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')
Run Code Online (Sandbox Code Playgroud)
Sch*_*aki 34
这是另一个没有额外行/ s来设置默认值的变体.bool始终具有一个赋值,以便可以在没有预先检查的逻辑语句中使用它.
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")
Run Code Online (Sandbox Code Playgroud)
hpa*_*ulj 33
关于什么type=bool和type='bool'可能意味着似乎有些混乱.一个(或两个)是否意味着'运行函数bool(),或'返回一个布尔值'?因为它type='bool'没有任何意义. add_argument给出'bool' is not callable错误,就像你使用的一样type='foobar',或者type='int'.
但是argparse有注册表可以让你定义像这样的关键字.它主要用于action,例如`action ='store_true'.您可以看到已注册的关键字:
parser._registries
Run Code Online (Sandbox Code Playgroud)
它显示一本字典
{'action': {None: argparse._StoreAction,
'append': argparse._AppendAction,
'append_const': argparse._AppendConstAction,
...
'type': {None: <function argparse.identity>}}
Run Code Online (Sandbox Code Playgroud)
定义了许多操作,但只有一种类型,默认类型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)
Run Code Online (Sandbox Code Playgroud)
parser.register()没有记录,但也没有隐藏.在大多数情况下,程序员并不需要了解它,因为type和action采取函数和类值.有很多stackoverflow示例为两者定义自定义值.
如果从前面的讨论中不明显,bool()并不意味着'解析字符串'.从Python文档:
bool(x):使用标准真值测试程序将值转换为布尔值.
与此形成鲜明对比
int(x):将数字或字符串x转换为整数.
Eva*_*ans 31
oneliner:
parser.add_argument('--is_debug', default=False, type=lambda x: (str(x).lower() == 'true'))
Run Code Online (Sandbox Code Playgroud)
sus*_*erg 18
我一直在寻找相同的问题,而且这个漂亮的解决方案是:
def str2bool(v):
return v.lower() in ("yes", "true", "t", "1")
Run Code Online (Sandbox Code Playgroud)
并使用它将字符串解析为boolean,如上所述.
小智 15
最简单和最正确的方法是:
from distutils.util import strtobool
parser.add_argument('--feature', dest='feature',
type=lambda x: bool(strtobool(x)))
Run Code Online (Sandbox Code Playgroud)
请注意,True 值是 y、yes、t、true、on 和 1;false 值为 n、no、f、false、off 和 0。如果 val 是其他值,则引发 ValueError。
foo*_*foo 13
除了@mgilson所说的,还应该注意的是,还有一种ArgumentParser.add_mutually_exclusive_group(required=False)方法可以使得强制执行该方法--flag并且--no-flag不会同时使用.
dl.*_*teo 12
一个非常类似的方法是使用:
feature.add_argument('--feature',action='store_true')
Run Code Online (Sandbox Code Playgroud)
并且如果您在命令中设置参数--feature
command --feature
Run Code Online (Sandbox Code Playgroud)
如果未设置type --feature,则参数将为True,参数默认始终为False!
Rus*_*ell 11
最简单。它不灵活,但我更喜欢简单。
parser.add_argument('--boolean_flag',
help='This is a boolean flag.',
type=eval,
choices=[True, False],
default='True')
Run Code Online (Sandbox Code Playgroud)
编辑:如果您不信任输入,请不要使用eval.
Zac*_*eck 11
这实际上已经过时了。对于 Python 3.7+,Argparse 现在支持布尔参数(搜索 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()
Run Code Online (Sandbox Code Playgroud)
另一件事要提的是:这将通过 argparse.ArgumentTypeError 阻止参数除 True 和 False 之外的所有条目。如果您出于任何原因想要尝试更改此设置,您可以为此创建一个自定义错误类。
小智 8
这适用于我期望的一切:
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
Run Code Online (Sandbox Code Playgroud)
代码:
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')
Run Code Online (Sandbox Code Playgroud)
小智 6
更简单的方法是使用如下.
parser.add_argument('--feature', type=lambda s: s.lower() in ['true', 't', 'yes', '1'])
Run Code Online (Sandbox Code Playgroud)
在之前遵循@akash-desarda的卓越答案/sf/answers/4170581341/之后,使用strtoboolvia ,后来,我决定直接lambda使用。strtobool
import argparse
from distutils import util
parser.add_argument('--feature', type=util.strtobool)
Run Code Online (Sandbox Code Playgroud)
是的,你是对的,strtobool返回的是int,而不是bool。但strtobool不会返回除0和之外的任何其他值1,并且 python 会将它们bool无缝且一致地转换为值。
>>> 0 == False
True
>>> 0 == True
False
>>> 1 == False
False
>>> 1 == True
True
Run Code Online (Sandbox Code Playgroud)
当收到错误的输入值时,例如
python yours.py --feature wrong_value
Run Code Online (Sandbox Code Playgroud)
与 argparse.Actionstrtobool进行比较lambda将产生稍微更清晰/易于理解的错误消息:
yours.py: error: argument --feature: invalid strtobool value: 'wrong_value'
Run Code Online (Sandbox Code Playgroud)
与这段代码相比,
parser.add_argument('--feature', type=lambda x: bool(util.strtobool(x))
Run Code Online (Sandbox Code Playgroud)
这将产生不太清晰的错误消息:
yours.py: error: argument --feature: invalid <lambda> value: 'wrong_value'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
323028 次 |
| 最近记录: |