Python argparse位置参数和子命令 [英] Python argparse positional arguments and sub-commands
问题描述
我正在使用argparse,并试图混合子命令和位置参数,然后出现以下问题.
I'm working with argparse and am trying to mix sub-commands and positional arguments, and the following issue came up.
此代码运行良好:
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument('positional')
subparsers.add_parser('subpositional')
parser.parse_args('subpositional positional'.split())
上面的代码将args解析为Namespace(positional='positional')
,但是当我将位置参数更改为具有nargs ='?'这样:
The above code parses the args into Namespace(positional='positional')
, however when I change the positional argument to have nargs='?' as such:
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument('positional', nargs='?')
subparsers.add_parser('subpositional')
parser.parse_args('subpositional positional'.split())
出现以下错误:
usage: [-h] {subpositional} ... [positional]
: error: unrecognized arguments: positional
这是为什么?
推荐答案
起初,我认为与jcollado相同,但是事实是,如果后续(顶层)位置参数具有特定的nargs
(nargs
= None
,nargs
=整数),那么它会按预期工作.当nargs
是'?'
或'*'
时,有时是'+'
时,它会失败.因此,我查看了代码,以了解发生了什么.
At first I thought the same as jcollado, but then there's the fact that, if the subsequent (top level) positional arguments have a specific nargs
(nargs
= None
, nargs
= integer), then it works as you expect. It fails when nargs
is '?'
or '*'
, and sometimes when it is '+'
. So, I went down to the code, to figure out what is going on.
它归结为拆分参数以使用的方式.为了弄清楚谁得到了什么,在您的情况下,对parse_args
的调用将像'AA'
这样的字符串中的参数汇总(对于位置参数,'A'
,对于可选参数,'O'
),最后生成一个正则表达式模式来与该摘要字符串匹配,具体取决于您通过.add_argument
和.add_subparsers
方法添加到解析器的操作.
It boils down to the way the arguments are split to be consumed. To figure out who gets what, the call to parse_args
summarizes the arguments in a string like 'AA'
, in your case ('A'
for positional arguments, 'O'
for optional), and ends up producing a regex pattern to be matched with that summary string, depending on the actions you've added to the parser through the .add_argument
and .add_subparsers
methods.
在每种情况下,例如,参数字符串最终都为'AA'
.变化的是要匹配的模式(可以在argparse.py
的_get_nargs_pattern
下看到可能的模式.对于subpositional
,它最终是'(-*A[-AO]*)'
,这意味着允许一个参数,后跟任意数量的选项或参数.对于positional
,它取决于传递给nargs
的值:
In every case, for you example, the argument string ends up being 'AA'
. What changes is the pattern to be matched (you can see the possible patterns under _get_nargs_pattern
in argparse.py
. For subpositional
it ends up being '(-*A[-AO]*)'
, which means allow one argument followed by any number of options or arguments. For positional
, it depends on the value passed to nargs
:
-
None
=>'(-*A-*)'
- 3 =>
'(-*A-*A-*A-*)'
(每个预期参数一个'-*A'
) -
'?'
=>'(-*A?-*)'
-
'*'
=>'(-*[A-]*)'
-
'+'
=>'(-*A[A-]*)'
None
=>'(-*A-*)'
- 3 =>
'(-*A-*A-*A-*)'
(one'-*A'
per expected argument) '?'
=>'(-*A?-*)'
'*'
=>'(-*[A-]*)'
'+'
=>'(-*A[A-]*)'
将附加这些模式,对于nargs=None
(您的工作示例),您将得到'(-*A[-AO]*)(-*A-*)'
,它与两组['A', 'A']
相匹配.这样,subpositional
将仅解析subpositional
(您想要的内容),而positional
将对其动作进行匹配.
Those patterns are appended and, for nargs=None
(your working example), you end up with '(-*A[-AO]*)(-*A-*)'
, which matches two groups ['A', 'A']
. This way, subpositional
will parse only subpositional
(what you wanted), while positional
will match its action.
对于nargs='?'
,您最终得到'(-*A[-AO]*)(-*A?-*)'
.第二组完全由可选模式组成,并且*
是贪婪的,这意味着第一组将字符串中的所有内容都模糊不清,最终识别出两个组['AA', '']
.这意味着subpositional
当然有两个参数,并最终令人窒息.
For nargs='?'
, though, you end up with '(-*A[-AO]*)(-*A?-*)'
. The second group is comprised entirely of optional patterns, and *
being greedy, that means the first group globs everything in the string, ending up recognizing the two groups ['AA', '']
. This means subpositional
gets two arguments, and ends up choking, of course.
有趣的是,nargs='+'
的模式是'(-*A[-AO]*)(-*A[A-]*)'
,只要您仅传递一个参数,它就会起作用.说subpositional a
,因为第二组中至少需要一个位置参数.同样,由于第一组是贪婪的,通过subpositional a b c d
会得到['AAAA', 'A']
,这不是您想要的.
Funny enough, the pattern for nargs='+'
is '(-*A[-AO]*)(-*A[A-]*)'
, which works as long as you only pass one argument. Say subpositional a
, as you require at least one positional argument in the second group. Again, as the first group is greedy, passing subpositional a b c d
gets you ['AAAA', 'A']
, which is not what you wanted.
简而言之:一团糟.我猜这应该被认为是一个错误,但不确定将模式转换为非贪婪模式会带来什么影响.
In brief: a mess. I guess this should be considered a bug, but not sure what the impact would be if the patterns are turned into non-greedy ones...
这篇关于Python argparse位置参数和子命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!