Python argparse:存储参数不匹配任何子解析器
Posted
技术标签:
【中文标题】Python argparse:存储参数不匹配任何子解析器【英文标题】:Python argparse: Store parameters not matching any subparser 【发布时间】:2021-03-15 01:43:18 【问题描述】:我正在使用 argparse 库来解析我的 python 脚本的参数。这是我的代码:
parser = argparse.ArgumentParser(
prog="confgit",
description="Git overhead for version control of your config files",
formatter_class=argparse.RawTextHelpFormatter, )
parser.add_argument(
"-c", "--config",
type=str,
default=DEFAULT_CONFIG_PATH,
dest="CONFIG_PATH",
help="load alternative config")
subparsers = parser.add_subparsers(help="Commands:")
subparsers.add_parser("include", help="Include file or directory in to repository").add_argument(
"file_to_include",
type=str,
action="store",
nargs="?",
const="",
default=False,
help="include file or directory in to repository")
subparsers.add_parser("exclude", help="Exclude file or directory in to repository").add_argument(
"exclude",
type=str,
action="store",
help="exclude file or directory from repository")
print(parser.parse_args())
我希望能够将不匹配任何子解析器的参数存储为字符串。例如
运行 myprogram include test.txt --config .config/cfg.txt
将导致:
Namespace(CONFIG_PATH='.config/cfg.txt', file_to_include='test.txt')
运行myprogram some text here
将导致:
Namespace(CONFIG_PATH='.config/default.txt', input="some other text")
我怎样才能做到这一点? 谢谢你的帮助
【问题讨论】:
通常我们将add_subparsers
结果分配给一个变量,然后将其与以下add_argument
一起使用。您的链接适用于一个参数,但让这位老 argparse
用户感到困惑。
【参考方案1】:
代码的帮助:
1940:~/mypy$ python3 stack65119253.py -h
usage: confgit [-h] [-c CONFIG_PATH] include,exclude ...
Git overhead for version control of your config files
positional arguments:
include,exclude Commands:
include Include file or directory in to repository
exclude Exclude file or directory in to repository
optional arguments:
-h, --help show this help message and exit
-c CONFIG_PATH, --config CONFIG_PATH
load alternative config
所以你可以提供一个带有值的optional
'-c'。
subparsers 参数是一个 positional
和 2 个 choices
。这不是必需的,但如果您确实提供了一个字符串,它将针对这些字符串进行测试。
1941:~/mypy$ python3 stack65119253.py include -h
usage: confgit include [-h] [file_to_include]
positional arguments:
file_to_include include file or directory in to repository
optional arguments:
-h, --help show this help message and exit
1941:~/mypy$ python3 stack65119253.py exclude -h
usage: confgit exclude [-h] exclude
positional arguments:
exclude exclude file or directory from repository
optional arguments:
-h, --help show this help message and exit
例如:
1946:~/mypy$ python3 stack65119253.py -c foobar
Namespace(CONFIG_PATH='foobar')
1946:~/mypy$ python3 stack65119253.py -c foobar test
usage: confgit [-h] [-c CONFIG_PATH] include,exclude ...
confgit: error: invalid choice: 'test' (choose from 'include', 'exclude')
1947:~/mypy$ python3 stack65119253.py -c foobar include
Namespace(CONFIG_PATH='foobar', file_to_include=False)
argparse
通过位置将字符串分配给positionals
。它不按值分配。也就是说,它不测试某些值,并根据它决定它是否合格。 choices
测试是在分配之后进行的。如果要按值分配,请使用optionals
。
parser.add_argument('--include', nargs='?')
parser.add_argument('--exclude')
parse+known_args
是处理unrecognized
参数的一种方式,但它无法绕过invalid choices
错误。
【讨论】:
我可以通过将nargs
位置放在前面来部分解决它,但由于某种原因,最后一个参数会针对 subparser 命令进行测试,而不是被 nargs slurped。我想这只是合乎逻辑的,因为这样就不可能在子命令之前有一个 nargs
位置并让子命令工作。
当你连续有 2 个位置时,一个是 ?
,另一个是 'plain',它会保留一个字符串作为第二个。由于过去补丁中的故障,subparsers
位置有点奇怪,并且在这种情况下表现为必需的位置,但在更大的图片中不是必需的。作为一般规则,subparsers
之前的位置不应该有变量nargs
。【参考方案2】:
如果用户不引用字符串"some other text"
,您只需将其视为3 个不同的参数["some", "other", "text"]
。但是要尽可能地处理它,您只需要在名为input
的参数上使用nargs
选项。 argparse
页面顶部有一个带有“数字累加器”的示例。
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
对 0 个或多个参数使用 *
而不是 +
,并将 integers
替换为您想要的任何参数名称。
经过进一步调查,当您有子解析器时,我上面写的内容将不起作用。我建议将您的 include
和 exclude
子命令设置为选项。无论如何都想做这不是明智的吗?在您当前的配置中,您只能包含或排除。
【讨论】:
在我的尝试中,我无法让它工作,因为它告诉我子解析器参数之一是必需的,尽管在 python 3.7 中他们引入了可选的子解析器,所以我不完全确定为什么它不起作用。不过,基本的想法应该可行。以上是关于Python argparse:存储参数不匹配任何子解析器的主要内容,如果未能解决你的问题,请参考以下文章
Python argparse:默认参数存储为字符串,而不是列表