Python argparse位置参数和子命令 [英] Python argparse positional arguments and sub-commands

查看:171
本文介绍了Python argparse位置参数和子命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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 = Nonenargs =整数),那么它会按预期工作.当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屋!

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