bounty将在5天后过期。回答此问题可获得+200声望奖励。BPL希望引起更多人对此问题的关注。
我正在尝试弄清楚如何正确使用内置的argparse模块来获得与git等工具类似的输出,在git中,我可以显示一个很好的帮助,所有的“根命令”都被很好地分组,即:
$ git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
<command> [<args>]
These are common Git commands used in various situations:
start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
init Create an empty Git repository or reinitialize an existing one
work on the current change (see also: git help everyday)
add Add file contents to the index
mv Move or rename a file, a directory, or a symlink
restore Restore working tree files
rm Remove files from the working tree and from the index
examine the history and state (see also: git help revisions)
bisect Use binary search to find the commit that introduced a bug
diff Show changes between commits, commit and working tree, etc
grep Print lines matching a pattern
log Show commit logs
show Show various types of objects
status Show the working tree status
grow, mark and tweak your common history
branch List, create, or delete branches
commit Record changes to the repository
merge Join two or more development histories together
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
switch Switch branches
tag Create, list, delete or verify a tag object signed with GPG
collaborate (see also: git help workflows)
fetch Download objects and refs from another repository
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
下面是我的尝试:
from argparse import ArgumentParser
class FooCommand:
def __init__(self, subparser):
self.name = "Foo"
self.help = "Foo help"
subparser.add_parser(self.name, help=self.help)
class BarCommand:
def __init__(self, subparser):
self.name = "Bar"
self.help = "Bar help"
subparser.add_parser(self.name, help=self.help)
class BazCommand:
def __init__(self, subparser):
self.name = "Baz"
self.help = "Baz help"
subparser.add_parser(self.name, help=self.help)
def test1():
parser = ArgumentParser(description="Test1 ArgumentParser")
root = parser.add_subparsers(dest="command", description="All Commands:")
# Group1
FooCommand(root)
BarCommand(root)
# Group2
BazCommand(root)
args = parser.parse_args()
print(args)
def test2():
parser = ArgumentParser(description="Test2 ArgumentParser")
# Group1
cat1 = parser.add_subparsers(dest="command", description="Category1 Commands:")
FooCommand(cat1)
BarCommand(cat1)
# Group2
cat2 = parser.add_subparsers(dest="command", description="Category2 Commands:")
BazCommand(cat2)
args = parser.parse_args()
print(args)
如果运行test1
,将得到:
$ python mcve.py --help
usage: mcve.py [-h] {Foo,Bar,Baz} ...
Test1 ArgumentParser
options:
-h, --help show this help message and exit
subcommands:
All Commands:
{Foo,Bar,Baz}
Foo Foo help
Bar Bar help
Baz Baz help
显然这不是我想要的,在那里我只看到了一个平面列表中的所有命令,没有分组或任何东西...所以下一个合乎逻辑的尝试是尝试将它们分组。但如果我运行test2
,我会得到:
$ python mcve.py --help
usage: mcve.py [-h] {Foo,Bar} ...
mcve.py: error: cannot have multiple subparser arguments
这显然意味着我没有正确地使用argparse来完成手头的任务。那么,是否有可能使用argparse来实现与git类似的行为呢?在过去,我一直依赖于“hacks”,所以我认为这里的最佳实践是使用add_subparsers
的概念,但似乎我没有正确理解这个概念。
1条答案
按热度按时间oyxsuwqo1#
argparse
本身并不支持这个功能--你不能嵌套子解析器,所以如果你想使用argparse来构建这样的cli,你需要在argparse
之上构建大量的逻辑,你可以设置nargs=argparse.REMAINDER
来收集子命令和参数,而不用argparse来解析它们,这意味着我们可以构建这样的东西:这是可怕的,丑陋的,结构不良的,但它意味着我们可以做到这一点:
或者这个:
如果你不想局限于
argparse
,像Click和Typer这样的库会让事情变得更简单,例如,上面的命令可以像这样使用Click来实现:好多了!