允许将带有nargs的位置命令行参数用标志分隔 [英] Allow positional command-line arguments with nargs to be seperated by a flag

查看:108
本文介绍了允许将带有nargs的位置命令行参数用标志分隔的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用argparse的程序.它需要1个必需的位置自变量,1个可选的位置自变量和1个标志自变量.

I have a program using argparse. It takes 1 required positional argument, 1 optional positional argument, and 1 flag argument.

类似的东西:

usage: test.py [-h] [-a A] b [c]

因此,我尝试使用此方法:

So, I tried using this:

parser = argparse.ArgumentParser()

parser.add_argument('-a')
parser.add_argument('b')
parser.add_argument('c', nargs='?', default=None)
print(parser.parse_args())

对于test.py B C -a Atest.py -a A B C来说,哪个效果很好.

Which works fine for test.py B C -a A and test.py -a A B C.

但是当我执行test.py B -a A C时,它会引发错误:

But when I do test.py B -a A C, it throws an error:

$ python3 test.py B -a A C
usage: test.py [-h] [-a A] b [c]
test.py: error: unrecognized arguments: C

那么,即使它们之间有一个标记,我如何使它接受要接受的可选位置参数呢?

So, how can I get it to accept the optional positional argument to be accepted even if there is a flag in between?

请注意,如果我删除了nargs='?', default=None,则此方法有效,但是它不是可选的. nargs='*'也会发生此问题,但nargs=N不会发生此问题(例如nargs=1nargs=2),nargs='+'不会发生. nargs=argparse.REMAINDER使其解析标志作为c(c = ['-a', 'A', 'C']a = None)

Note that this works if I remove the nargs='?', default=None, but then it's not optional. The problem also happens with nargs='*', but this doesn't happen for nargs=N (e.g. nargs=1, nargs=2) and doesn't happen for nargs='+'. nargs=argparse.REMAINDER makes it parse the flags as part of c (c = ['-a', 'A', 'C'], a = None)

推荐答案

这是一个已知问题,关于SO和Python错误/问题,都没有一个简单的解决方法. https://bugs.python.org/issue15112

This is a known issue, both here on SO and Python bug/issues, and doesn't have an easy fix. https://bugs.python.org/issue15112

这是基本解析算法的结果.这会尝试解析位置信息,直到下一个可选标志.然后解析标记的选项(以及它需要的许多参数).然后解析下一批职位,等等.

It's the result of the basic parsing algorithm. This trys to parse positionals up to the next optional's flag. Then parse the flagged option (and however many arguments it needs). Then parse the next batch of positions, etc.

当解析器处理b时,即使只有一个字符串,它也可以处理c. c不需要任何内容​​.这意味着c第一次处理位置信息时会被用完".

When the parser handles b, it can also handle c, even if there is just one string. c requires nothing. That means c gets 'used up' the first time it processes positionals.

In [50]: parser.parse_args(['one'])
Out[50]: Namespace(a=None, b='one', c=None)
In [51]: parser.parse_args(['one','two'])
Out[51]: Namespace(a=None, b='one', c='two')
In [52]: parser.parse_args(['one','-a','1','two'])
usage: ipython3 [-h] [-a A] b [c]
ipython3: error: unrecognized arguments: two
An exception has occurred, use %tb to see the full traceback.

SystemExit: 2

/home/paul/.local/lib/python3.6/site-packages/IPython/core/interactiveshell.py:2971: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
In [53]: parser.parse_known_args(['one','-a','1','two'])
Out[53]: (Namespace(a='1', b='one', c=None), ['two'])

c用尽(即使它只是获得默认值),也没有任何东西可以消耗最后一个字符串.这是一个额外".

With c used up (even though it just gets the default), there's nothing to consume the last string. It is an 'extra'.

Python 3.7添加了解决此问题的解析方法parse_intermixed_args. https://docs.python.org/3/library/argparse.html #intermixed-parsing

Python 3.7 has added a parsing method that solves this issue, parse_intermixed_args. https://docs.python.org/3/library/argparse.html#intermixed-parsing

In [447]: import argparse37
In [448]: p = argparse37.ArgumentParser()
In [449]: p.add_argument('pos1');
In [450]: p.add_argument('-a');
In [451]: p.add_argument('pos2', nargs='?');

In [453]: p.parse_args('1 2 -a foo'.split())
Out[453]: Namespace(a='foo', pos1='1', pos2='2')

In [454]: p.parse_args('1 -a foo 2'.split())
usage: ipython3 [-h] [-a A] pos1 [pos2]
ipython3: error: unrecognized arguments: 2
...

In [455]: p.parse_intermixed_args('1 -a foo 2'.split())
Out[455]: Namespace(a='foo', pos1='1', pos2='2')

In [456]: p.parse_intermixed_args('1 2 -a foo'.split())
Out[456]: Namespace(a='foo', pos1='1', pos2='2')

它是作为允许在"*"位置中间标记操作的一种方式添加的.但最终在这种情况下以?"开始工作动作.请注意文档中的注意事项;它可能无法处理所有argparse功能.

It was added as a way of allowing a flagged Action in the middle of a '*' positional. But ends up working in this case with '?' Actions. Note the caution in the docs; it may not handle all argparse features.

实际上,它会停用positionals,执行parse_known_args来获取所有optionals,然后仅使用positonals来解析extras.有关详细信息,请参见parse_known_intermixed_args的代码.

In effect it deactivates the positionals, does a parse_known_args to get all optionals, and then parses the extras with just the positonals. See the code of parse_known_intermixed_args for details.

这篇关于允许将带有nargs的位置命令行参数用标志分隔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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