你如何让 argparse 选择一个默认的子解析器? [英] How do you get argparse to choose a default subparser?

查看:20
本文介绍了你如何让 argparse 选择一个默认的子解析器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 script.py 中有以下代码:

I have the following code in script.py:

import argparse

parser = argparse.ArgumentParser()
sp = parser.add_subparsers(dest='command')
sp.default = 'a'

a_parser = sp.add_parser('a')
b_parser = sp.add_parser('b')

a_parser.add_argument('--thing', default='thing')
b_parser.add_argument('--nothing', default='nothing')

args = parser.parse_args()
print(args)

我可以用三种不同的方式来称呼它:

I can call this three different ways:

$ python3 script.py
Namespace(command='a')
$ python3 script.py a
Namespace(command='a', thing='thing')
$ python3 script.py b
Namespace(command='b', nothing='nothing')

这只有一个问题:我想要的是,如果我在命令行上提供零个参数,a_parser 将成为结束解析和做事.显然不是,sp.default 只是设置 command='a',不是我所期望的,也就是说,哦,是的,用户没有在命令行上提供任何参数,但我知道这应该由 a_parser 处理.这是 Namespace(command='a', thing='thing')!"

There's only one problem with this: what I want is that if I provide zero arguments on the command line is for a_parser to be the one that ends out parsing and doing stuff. Clearly it's not, the sp.default is just setting command='a', not what I expect, which is to say, "Oh yeah, the user didn't provide any arguments on the command line, but I know that this should be processed by a_parser. Here's Namespace(command='a', thing='thing')!"

有没有办法让我可以用 argparse 做到这一点?我已经寻找了一些不同的选择,但它们似乎都没有真正提供我所追求的.我想我可以通过制作 3 个不同的 ArgumentParsers 然后将参数传递给每个人来做一些麻烦事,尽管这听起来有点恶心.

Is there a way that I can do this with argparse? I've looked for a few different options, but none of them really seem to provide what I'm after. I guess I could do some jiggery with making 3 distinct ArgumentParsers and then passing on the arguments to each of them, though that sounds a bit gross.

还有更好的选择吗?

推荐答案

首先是一个历史记录 - 子解析器不是可选的,它们仍然不是 Python2.它们在 Py3 中是可选的这一事实是几年前引入的一个错误.所需参数的测试发生了变化,并且子解析器(一种位置)陷入了困境.如果操作正确,您应该必须将子解析器显式设置为不需要.

First a historical note - subparsers were not optional, and they still aren't in Python2. The fact that they are optional in Py3 is something of a bug that was introduced several years ago. There was a change in the test for required arguments, and subparsers (a kind of positional) fell through the cracks. If done right you should have had to explicitly set subparsers as not-required.

子解析器的行为不像其他非必需参数、带有 nargs='?' 或标记为不带 required 参数的参数.

Subparsers don't behave like other non-required arguments, ones with nargs='?' or flagged without the required parameter.

无论如何,您的sp.default 定义了将放入command dest 中的值,但它不会触发a_parser.command='a' 永远不会被评估".

In any case, your sp.default defines the value that will be put in the command dest, but it does not trigger the use of a_parser. That command='a' is never 'evaluated'.

使用 parse_known_args 可能允许您使用 a_parser 贬值剩余的字符串.

The use of parse_known_args might allow you to devaluate the remaining strings with a_parser.

没有任何参数,我们可以:

Without any arguments, we can do:

In [159]: args, extras = parser.parse_known_args([])
In [160]: args
Out[160]: Namespace(command='a')
In [161]: extras
Out[161]: []

然后有条件地运行a_parser(如果命令是'a'但没有'thing')

Then conditionally run a_parser (if command is 'a' but no 'thing')

In [163]: a_parser.parse_args(extras,namespace=args)
Out[163]: Namespace(command='a', thing='thing')

但是如果我尝试包含一个 --thing 值:

But if I try to include a --thing value:

In [164]: args, extras = parser.parse_known_args('--thing ouch'.split())
usage: ipython3 [-h] {a,b} ...
ipython3: error: argument command: invalid choice: 'ouch' (choose from 'a', 'b')

它尝试将ouch"解析为子解析器名称.主解析器对 --thing 参数一无所知.

It tries to parse the 'ouch' as subparser name. The main parser doesn't known anything about the --thing argument.

正如我在今天的另一个 argparse 问题中所解释的,顶级解析器会解析输入,直到找到适合子解析器"命令的内容(或者在本示例中引发错误).然后它将解析传递给子解析器.之后它不会继续解析.

As I explained in the other argparse question today, the toplevel parser parses the inputs until it finds something that fits the 'subparsers' command (or in this example raises an error). Then it passes the parsing to the subparser. It does not resume parsing after.

在子解析器参数之后添加顶级 argparse 参数

如何设置使用 Argparse 模块和 Python 2.7 的默认子解析器

我对这个 Py2 请求的回答可能对你有用.我首先使用没有子解析器的解析器运行 parse_known_args,然后有条件地运行处理子解析器的第二个解析器.

My answer to this Py2 request might work for you. I first run a parse_known_args with a parser that doesn't have subparsers, and conditionally run a second parser that handles the subparsers.

In [165]: firstp = argparse.ArgumentParser()
In [166]: args, extras = firstp.parse_known_args('--thing ouch'.split())
In [167]: args
Out[167]: Namespace()

如果 extras 没有 'a' 或 'b' 调用 a_parser(或者只需查看 sys.argv[1:]> 直接):

If extras doesn't have 'a' or 'b' call a_parser (alternatively just look at sys.argv[1:] directly):

In [168]: extras
Out[168]: ['--thing', 'ouch']
In [169]: a_parser.parse_args(extras)
Out[169]: Namespace(thing='ouch')

或修改 extras 以包含缺少的 subparser 命令:

Or modify extras to include the missing subparser command:

In [170]: extras = ['a']+extras
In [171]: parser.parse_args(extras)
Out[171]: Namespace(command='a', thing='ouch')

无论如何,optional 子解析器在argparse 中没有得到很好的开发.这是前一段时间所做更改的副作用,而不是经过深思熟虑的功能.

In any case, optional subparsers is not well developed in argparse. It's the side effect of a change made a while back, rather than a well thought out feature.

这篇关于你如何让 argparse 选择一个默认的子解析器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆