【问题标题】:How to argparse with nargs+ and subcommands如何使用 nargs+ 和子命令进行 argparse
【发布时间】:2017-01-19 12:50:13
【问题描述】:

我正在尝试创建一个类似的命令

prog [-h] [-i ID [ID ...]] | -x [SOMETHING] 
     {cmd1,cmd2,cmd3}...

所以基本上在顶层,我有一个解析器,它对 -i 和 -x 选项有一个互斥组,然后按照这些(可能还有其他)选项,我有一个要运行的命令。每个命令都有自己使用的一组选项。我可以使用add_subparsers() 使命令正常工作,但我遇到的问题是当我尝试向具有nargs='+' 的根解析器添加参数时。当我这样做时,它会吞下-i 的所有参数,认为该命令是一个参数而不是一个 ID。

有没有办法解决这个问题?似乎它必须查看 -i 的参数以查找命令字,然后告诉 argparse 它应该在该点恢复解析。

【问题讨论】:

  • 如果不是太大,你能给我们看一个minimal reproducible example/你的代码吗?
  • 结帐Click 使用 python 构建 CLI 并省去您的麻烦。
  • @garnertb +1。可以确认,click 很棒,可以很好地处理子命令。

标签: python argparse


【解决方案1】:

我不得不多次阅读您的描述,但我认为这是问题所在:

prog -i id1 id2 cmd1 -foo 3 ....

它给出了一些关于找不到{cmd1,cmd2,cmd3} 的警告。确切的错误可能会有所不同,因为在某些版本中 subparsers 实际上并不需要。

在任何情况下,-i 的参数都是 ['id1','id2','cmd1'],直到下一个 - 标志。对于主解析器,子解析器参数只是另一个positional 一个(带有choices)。将字符串分配给-i 时,它不会检查字符串是否与cmds 之一匹配。它只是看它是否以-开头。

在上下文中使用nargs='+'(或“*”)的唯一方法是包含其他一些标记的参数,例如

prog -i id1 id2 -x 3 cmd1 --foo ...

我知道这与您的 mutually_exclusive 群组不符。

基本点是非标志字符串是根据位置分配的,而不是值。对于变量nargs,您必须有某种明确的列表终止符。

从侧边栏

Argparse nargs="+" is eating positional argument

除了你的下一个位置是 subparsers cmd 之外,它是相似的。

==============

带有 '+' 的位置将在子解析器 cmd 之前工作

usage: prog [-h] foo [foo ...] {cmd1,cmd2} ...

In [160]: p1.parse_args('1 22 3 cmd1'.split())
Out[160]: Namespace(cmd='cmd1', foo=['1', '22', '3'])

但这是因为foocmd 的字符串分配有一个regex 模式测试。

usage: prog [-h] [--bar BAR [BAR ...]] {cmd1,cmd2} ...

字符串被分配给bar,而不考虑以下位置cmd的需要。如http://bugs.python.org/issue9338 的建议补丁中所示,更改此行为并非易事。它需要一个额外的前瞻性试错循环。

【讨论】:

  • 由此推论:nargs='+' 通常不适合与他人相处。多次使用单个参数 (-i id1 -i id2 cmd1) 或定义选项以采用单个可解析参数 (-i id1,id2 cmd1)。
  • 是的,这是我想出的简单解决方案,但并不理想。我希望它足够聪明,可以知道命令是选项并继续解析,而不必知道执行逗号分隔列表、--等的“秘诀”。理想情况下,解析器会检查 id2 并意识到它是一个命令和解析。本质上,我想做一个“查看下一个 id。如果不在命令中,则附加到 ids,否则解析为命令”
  • 这与argparse的基本解析方法相反。 optparse 可以做你想做的事情。但是argparse 完全来自位置和标志字符串。它不会“提前”查看下一个字符串是否符合某些值标准。它首先将字符串分配给 Action,然后运行 ​​typechoices 测试,而不是相反。
  • 我添加了一个错误问题的链接,该问题试图实现一种前瞻性。
猜你喜欢
  • 1970-01-01
  • 2014-11-30
  • 2018-12-30
  • 2013-06-02
  • 2014-10-11
  • 2011-09-15
  • 2015-05-07
  • 2017-11-01
相关资源
最近更新 更多