【问题标题】:Python argparse, run one or more sub-commandsPython argparse,运行一个或多个子命令
【发布时间】:2014-10-08 17:29:40
【问题描述】:

我正在尝试编写一个能够执行多个子命令的程序。 argparse 模块非常有用,但我认为它缺乏指定多个子命令的能力。例如,如果我有以下代码:

parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers()

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs='+', help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt1', help='option 1 help')
subcommand_b.add_argument('--opt2', help='option 2 help')
subcommand_b.add_argument('--opt3', nargs='+', help='option 3 help')

parser.parse_args()

我无法在命令行上同时指定 subcommand_a 和 subcommand_b。我一次只能做其中一个。我想这将需要自定义操作,甚至可能需要子类化 argparse,但我不确定从哪里开始。我希望能够像下面这样调用这个程序:

./prog.py subcommand_a FOO --opt1=bar --opt2 1 2 3 -- subcommand_b BAR --opt1='foo' --opt3 a b c --

有什么想法吗?

【问题讨论】:

  • 使用nargs='+',您需要--opt2 1 2 3,而不是--opt2=1 2 3。后者将1 分配给opt2,但对2 3 不执行任何操作。
  • 你应该调查docopt。它是一个使用您的手册​​页来解析参数和选项的框架。它使执行更复杂的参数规范变得更加容易,使它们更易于支持,在大多数语言中实现,并且您可以免费获得手册页!

标签: python argparse


【解决方案1】:

您的问题与几个月前问的问题基本相同

Multiple invocation of the same subcommand in a single command line

那个人想多次调用同一个子命令,但问题相同 - 如何处理多个subparsers 参数。

解决方案要么在将命令行传递为单独解析的片段之前拆分命令行,要么从一个解析中收集“未使用”片段以供第二个或第三个使用。

以下是对返回 2 个命令的代码的调整:

import argparse
parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers(dest='cmd')

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs=3, help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt1', help='option 1 help')
subcommand_b.add_argument('--opt2', help='option 2 help')
subcommand_b.add_argument('--opt3', nargs=3, help='option 3 help')

argv = "subcommand_a FOO --opt1=bar --opt2 1 2 3 subcommand_b BAR --opt1=foo --opt3 a b c"
rest = argv.split()
while rest:
    [args, rest] = parser.parse_known_args(rest)
    print args
    print rest

哪个打印:

Namespace(cmd='subcommand_a', opt1='foo', opt2=['1', '2', '3'], req1='FOO')
['subcommand_b', 'BAR', '--opt3', 'a', 'b', 'c']
Namespace(cmd='subcommand_b', opt1=None, opt2=None, opt3=['a', 'b', 'c'], req1='BAR')
[]

我删除了'--'(见我其他答案的结尾)

我将 opt2opt3 更改为采用 3 个参数,而不是变量 +。对于+,它无法判断opt2 列表的结束位置和下一个命令的开始位置。

不同的命令采用不同的选项(标志)也很重要。请注意,第一个 opt1 以第二个值“foo”结束,第二个命令没有留下任何值。有关问题和解决方法的讨论,请参阅其他线程。

【讨论】:

  • 感谢 hpaulj,我希望能够将变量 '+' 保留为 nargs,所以我认为我需要将其解析出来并将结果列表传递给 parse_known_args。不过,这让我得到了大部分的帮助。
【解决方案2】:

我已经进行了一些测试并将子命令更改为其他有效的字符串。 如果你使用:

parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers()

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs='+' help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt3', help='option 1 help')
subcommand_b.add_argument('--opt4', help='option 2 help')
subcommand_b.add_argument('--opt5', nargs='+', help='option 3 help')

parser.parse_args()

它有效。

我进行了一些研究,但没有找到具有相同字符串的子命令。文档的概述也没有说什么。我认为这是一个限制(通过选择)或错误。 也许你可以在Source Code Hosting查看它

【讨论】:

  • '具有相同字符串的子命令' - 你是在谈论 --opt2=1 2 3 参数吗?
  • 不,有它的名字。选择 1,选择 2,选择 3。在子命令 opt1 和 opt2 中。尝试将它们更改为不同的名称。
  • 通常子命令可以有重复的参数标志。但那是只给出和解析一个子命令的时候。在这里,它们可能会造成混乱。
  • 我理解更改子命令选项名称的原因,但不幸的是,这对于我正在处理的应用程序来说是不可能的
猜你喜欢
  • 2017-01-31
  • 2015-10-20
  • 1970-01-01
  • 2019-09-23
  • 2018-12-03
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
相关资源
最近更新 更多