【问题标题】:How do I specify two required arguments, including a subcommand, using 'argparse'?如何使用“argparse”指定两个必需的参数,包括一个子命令?
【发布时间】:2015-11-02 05:20:20
【问题描述】:

有没有办法在argparse 中指定两个必需的参数,一个对应于子命令,另一个对应所有子命令。

我能做到的最接近的似乎是与

import argparse

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers(help='', dest='command',  metavar='COMMAND', title='required arguments',
                                   description='two arguments are required')
parser.add_argument('config', metavar='CONFIG', action='store', help='the config to use')

cmda_parser = subparsers.add_parser('cmdA',  help='a first command')
cmdb_parser = subparsers.add_parser('cmdB',  help='the second operation')
cmdc_parser = subparsers.add_parser('cmdC',  help='yet another thing')

print(parser.parse_args())

给了

usage: enigma.py [-h] COMMAND ... CONFIG

positional arguments:
  CONFIG      the config to use

optional arguments:
  -h, --help  show this help message and exit

required arguments:
  two arguments are required

  COMMAND
    cmdA      a first command
    cmdB      the second operation
    cmdC      yet another thing

以及不显示CONFIG 的子命令的帮助;但我想要的是

usage: enigma.py [-h] COMMAND CONFIG

required arguments:
  two arguments are required

  COMMAND
    cmdA      a first command
    cmdB      the second operation
    cmdC      yet another thing

  CONFIG      the config to use

optional arguments:
  -h, --help  show this help message and exit

以及每个显示CONFIG 的子命令的帮助,例如。

usage: enigma.py cmdA CONFIG [-h] 

    required arguments:

      CONFIG      the config to use

optional arguments:
  -h, --help  show this help message and exit

有没有办法做到这一点?

我如何指定 两个 必需参数,其中一个是子命令,第二个“传播”​​到每个子命令作为必需参数?

【问题讨论】:

  • 你试过先定义CONFIG吗?
  • @hpaulj:CONFIG 在 COMMAND 之后。
  • 然后为每个子解析器定义它。
  • @hpaulj:问题的重点是看是否可以避免。
  • 避免这种情况的目的是什么?它会使代码更清晰,还是更短? argparse 中没有“传播”机制。

标签: python python-2.7 argparse


【解决方案1】:

解析器可以使用parents 属性从另一个解析器“继承”参数。

import argparse

parser = argparse.ArgumentParser()

# Put common subparser arguments here. Each sub parser will have
# its own -h option, so disable it on the shared base.
subbase = argparse.ArgumentParser(add_help=False)
subbase.add_argument('config', metavar='CONFIG', action='store', help='the config to use')

subparsers = parser.add_subparsers(help='', dest='command',  metavar='COMMAND', title='required arguments',
                                   description='two arguments are required')

# Add subbase to the parent list for each subparser.
cmda_parser = subparsers.add_parser('cmdA', parents=[subbase],  help='a first command')
cmdb_parser = subparsers.add_parser('cmdB', parents=[subbase], help='the second operation')
cmdc_parser = subparsers.add_parser('cmdC', parents=[subbase], help='yet another thing')

print(parser.parse_args())

【讨论】:

  • 接近了,我想。但这并没有将CONFIG 列为在没有指定参数的情况下请求帮助时的两个必需参数之一。
  • 您必须使用script.py cmdA -h 才能看到CONFIG 作为参数列出。这是子解析器的参数,而不是主解析器。
  • 这涉及到一个不同的问题 - 主解析器帮助中没有显示任何子解析器参数。每个解析器(包括主解析器)只显示自己的参数。
  • stackoverflow.com/questions/20094215/… 是关于显示主解析器和子解析器帮助的几个 SO 问题之一。
  • 不是我想要的,但它说明了为什么 argparse 阻止我这样做。这是我用过的最不经过深思熟虑的 Python API 之一。
【解决方案2】:

使用您定义的解析器,COMMANDCONFIG 都是必需的。举个例子

python myprog cmdA

你应该得到一个错过参数的错误。在较新的版本上,它将是明确的

0826:~/mypy$ python3.5 stack33463052.py cmdA 
usage: stack33463052.py [-h] COMMAND ... CONFIG
stack33463052.py: error: the following arguments are required: CONFIG

但是,是的,COMMAND 没有出现在子解析器的帮助中。那是因为 subparse 对此一无所知。它是为主解析器定义的。

如果我将 CONFIG 定义移到 subparsers 创建之前,我会得到:

0833:~/mypy$ python stack33463052.py tst cmdA -h
usage: stack33463052.py CONFIG cmdA [-h]

optional arguments:
  -h, --help  show this help message and exit

现在CONFIG 出现在用法中。这是因为代码在定义子解析器时就知道这个参数。但是 - 在寻求帮助时,我必须包含 CONFIG 的值。


(编辑) CONFIG 出现在 cmdA 用法中,因为它是在创建解析器时添加到它的 prog 属性中的:

 print(cmda_parser.prog)
 'stack33463052.py CONFIG cmdA'

但是,如果稍后将参数添加到 parser,则不会修改 prog


在下文中,cmdA 被用作 CONFIG 的参数,而不是 COMMAND,因此我获得了默认的主解析器帮助。

0833:~/mypy$ python stack33463052.py cmdA -h
usage: stack33463052.py [-h] CONFIG COMMAND ...

positional arguments:
  CONFIG      the config to use

optional arguments:
...

对于主解析器,CONFIGCOMMAND 都是必需的位置。 COMMAND 没有什么特别之处,只是它定义了 3 个 choices

为每个子解析器定义CONFIG 可能是最好的选择。它需要更多的输入,但它会显示在正确的帮助中。如果从概念上讲,它与命令的联系比主解析器更紧密,那么它需要与它们一起定义。所有命令都需要它这一事实并不重要。

一般来说,在使用子解析器时,最好对主要解析器值(如 vebosity 和日志记录)使用可选项,并在子解析器中定义其余值。它使解析器之间的工作分工更加清晰。如果需要,我可以详细说明。

没有传播机制。但我当然可以编写一个函数,为每个子解析器添加一个公共参数。

def foo(subparsers, *args, **kwargs):
   sub = subparsers.add_parser(*args, **kwargs)
   sub.add_argument('config')
   return sub

在交互式 shell 中运行解析器设置并检查每个命令创建的对象是有益的 - parsersubparserscmda_parser 等。@ 的参数列表(Action 对象) 987654350@ 知道在parser._actions

argparse 模块中的程序清晰和简洁意味着parsercmda_parser 是不同的ArgumentParser 对象。一个不仅仅是另一个的模式或方法。 subparsers 对象(Action 子类)是 parsercmda_parser 之间的唯一正式链接。

也试试:

parser.print_help() # or parser.print_usage()
cmda_parser.print_help()

这有助于表明 2 个解析器的 help 是独立的。

【讨论】:

    猜你喜欢
    • 2012-06-24
    • 2020-10-03
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 2020-03-22
    • 2017-08-13
    • 2014-07-10
    相关资源
    最近更新 更多