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

查看:25
本文介绍了允许带有 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,然后解析 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天全站免登陆