我试图获得以下行为:

  • python test.pyfoo=False
  • python test.py --foofoo=True
  • python test.py --foo boolfoo=bool

当我使用

parser.add_argument('--foo', nargs='?', default=False, const=True)

然而,如果我加上type=bool,试图强制对布尔值进行强制转换,它就会崩溃.在这种情况下

python test.py --foo False

实际上最终存储了foo=True个.发生什么事??

推荐答案

你需要那个图案吗?--foo--foo <value>加在一起,对于布尔switch 来说,不是常用的模式.

至于您的问题,请记住命令行值是stringtype=bool表示希望应用bool(entered-string-value).对于--foo False,这意味着bool("False"),产生True;所有非空字符串都是真的!参见Why is argparse not parsing my boolean flag correctly?.

与支持--foo/--foo <string value>不同,我建议您使用--foo表示True,删除参数值,并添加--no-foo选项以显式设置False:

parser.add_argument('--foo', default=False, action='store_true')
parser.add_argument('--no-foo', dest='foo', action='store_false')

--no-fooswitch 上的dest='foo'加法确保它存储的False值(通过store_false)最终位于相同的args.foo属性上.

从Python 3.9开始,还可以使用argparse.BooleanOptionalAction action类:

parser.add_argument("--foo", action=argparse.BooleanOptionalAction)

它会有同样的效果,处理--foo--no-foo来设置和清除标志.

如果您有一些其他配置机制,将foo设置为True,并且需要使用命令行switch 再次覆盖,那么您只需要--foo / --no-foo个组合.--no-<option>是一个广泛采用的标准,用于反转布尔命令行switch .

如果你特别需要一个--no-foo反转switch (因为只有omitting --foo就意味着"假"),那么就坚持action='store_true'选项.这使您的命令行简单明了!

但是,如果您的用例或其他约束特别要求您的命令行must具有一些--foo (true|false|0|1)王支持,那么添加您自己的转换器:

def str_to_bool(value):
    if isinstance(value, bool):
        return value
    if value.lower() in {'false', 'f', '0', 'no', 'n'}:
        return False
    elif value.lower() in {'true', 't', '1', 'yes', 'y'}:
        return True
    raise ValueError(f'{value} is not a valid boolean value')

parser.add_argument('--foo', type=str_to_bool, nargs='?', const=True, default=False)
  • const值用于省略参数值的nargs='?'个参数.在这里,当使用--foo时设置foo=True.
  • 当根本不使用switch 时,使用default=False.
  • type=str_to_bool用于处理--foo <value>案件.

演示:

$ cat so52403065.py
from argparse import ArgumentParser

parser = ArgumentParser()

def str_to_bool(value):
    if value.lower() in {'false', 'f', '0', 'no', 'n'}:
        return False
    elif value.lower() in {'true', 't', '1', 'yes', 'y'}:
        return True
    raise ValueError(f'{value} is not a valid boolean value')

parser.add_argument('--foo', type=str_to_bool, nargs='?', const=True, default=False)

print(parser.parse_args())
$ python so52403065.py
Namespace(foo=False)
$ python so52403065.py --foo
Namespace(foo=True)
$ python so52403065.py --foo True
Namespace(foo=True)
$ python so52403065.py --foo no
Namespace(foo=False)
$ python so52403065.py --foo arrbuggrhellno
usage: so52403065.py [-h] [--foo [FOO]]
so52403065.py: error: argument --foo: invalid str_to_bool value: 'arrbuggrhellno'

Python-3.x相关问答推荐

错误2没有这样的文件或目录website_content.txt""

基于另一个数据帧计算总和

链接列未延伸到数据框的末尾

CSV-DAT 转换时将引号添加到数据中

不同的焦点顺序和堆叠顺序 tkinter

需要找到完全匹配并使用正则表达式替换

将水平堆叠的数据排列成垂直

在 string.find() 条件下加入两个 Dataframes

Pandas:从 Pandas 数据框中的 1 和 0 模式中获取值和 ID 的计数

避免重复连续字符但不包括一个特定字符的正则表达式

如何在python中将列表转换为其他格式

如何模拟 Django 模型对象(及其方法)?

pysftp vs. Paramiko

__new__ 方法给出错误 object.__new__() 只接受一个参数(要实例化的类型)

Python configparser 不会接受没有值的键

0 是 0 == 0(#evaluates 为真?)

用于 unicode 大写单词的 Python 正则表达式

将列表列表转换为Python中的字典字典

尾部斜杠的 FastAPI 重定向返回非 ssl 链接

如何避免使用我的 python 包构建 C 库?