argparse可以用来处理复杂的混合和匹配命令行参数(没有选项)吗?

时间:2016-03-08 02:55:22

标签: python python-3.x argparse

我正在将shell脚本转换为Python。

shell脚本支持这样的参数。

Usage: foo [-h] [-v] [COMMAND] [COMMAND_ARG]...

One or more of the following commands may be specified in the same
command line invocation of this script.

Commands:
  print            Print lines in CSV.
  search PATTERN   Print only lines that match PATTERN.
  remove PATTERN   Remove all lines that match PATTERN.
  convert          Convert CSV file to XLS file.
  limit N          Show a maximum of N results (default 10).
  all              Do not limit lines.

Options:
  -h, --help       Show help.
  -v, --version    Show version.

“命令”部分中列出的一个或多个参数可以混合使用 匹配,但其中一些是相互排斥的。

例如,以下所有内容都是有效的命令行调用。

# Prints 10 lines from CSV
foo print

# Prints 3 lines from CSV
foo print limit 3
foo limit 3 print

# Prints all lines from CSV
foo print all
foo all print

# Converts 10 lines from CSV into XLS
foo convert

# Converts 3 lines from CSV into XLS
foo limit 3 convert
foo convert limit 3

# Search for the word "foo" in CSV and print 3 such lines
foo search "\<foo\>" limit 3
foo limit 3 search "\<foo\>"

但是,printsearchremoveconvert是相互的 独家。所以以下内容无效。

foo print convert
foo search "\<foo\>" remove "\<foo\>"

是否可以使用这些来处理命令行参数 argparse?或者我最好自己循环sys.argv, 使用我自己的代码处理这些情况,这也意味着我有 负责更新帮助消息和任何必要的验证 每当支持的参数列表发生变化时?

注意:我不想依赖argparse模块的任何内部实现来实现此目的。我只想依赖公开记录的argparse API。如果用argparse公开记录的API无法解决这个问题,那就没问题了,那就是答案。在这种情况下,我将通过循环sys.argv来处理命令行参数,类似于shell脚本通过循环"$@"处理参数的方式。

2 个答案:

答案 0 :(得分:1)

--limit--all是选项的变体,其余的是子分析符argparse非常适合。

如果没有严重的问题,您无法运行多个子分析符(例如printlimit)。加limitall在概念上是非常不同的参数。其他是命令 - 这样做。 limitall是修饰符。

limitall与其他所有人合作,或仅与printsearch合作。对于那些次级分析者来说,它们可能更有意义。

另请注意,argparse的一大优点是它会生成使用情况,帮助和错误消息。当你做一些不寻常的事情时,你需要考虑那些消息。您如何清楚地告诉您的用户他们可以limit使用print而不是convert?或者他们无法同时使用limitall;或那一个压倒另一个。

但如果您遇到这些名称/标志,并且无法添加--,请不要打扰argparse。不要费心改变已经有效的东西。

argparse(以及optparsegetopt)中的基本哲学是使用标记字符串(' - '),您希望将内容与操作匹配,并处理其余内容按命令。 argparse期望根据位置解析您的字符串,而不是内容。

答案 1 :(得分:0)

它可以解决这个问题,只是不太像你这样做。您可以使用subcommands/subparsers进行打印,搜索,删除和转换,并将其他“命令”(顶级命令上的选项)定义为开关,如果它们对所有人都是通用的,则在顶级解析器上命令,或者如果它们不常见,则在各个子分析符/子命令上。

现在,在这种特殊情况下,您似乎甚至没有针对每个子命令的唯一行为,因此您可能只是使用单个位置参数和两个开关:

parser = argparse.ArgumentParser()
parser.add_argument('action', choices=('print', 'search', 'remove', 'convert')
parsecount = parser.add_mutually_exclusive_group()
parsecount.add_argument('--all', dest='limit', action='store_const', const=None)
parsecount.add_argument('--limit', type=int)
parser.set_defaults(limit=10)

如果需要,位置action参数可以更改为单个子分析符,但在这种情况下,似乎所有可能的命令都允许alllimit