您如何获得argparse来选择默认的子解析器? [英] How do you get argparse to choose a default subparser?

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

问题描述

我在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问题中所解释的那样,顶级解析器对输入进行解析,直到找到适合'subparsers'命令的内容(否则在此示例中会引发错误).然后,它将解析传递给子解析器.之后,它不会继续解析.

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.

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

如何设置带有python 2.7的Argparse模块的默认子解析器

我对此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')

在任何情况下,在argparse中都无法很好地开发optional子解析器.这是前一段时间所做的更改的副作用,而不是经过深思熟虑的功能.

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天全站免登陆