Python 允许argparse nargs="+&引用;使用选项接受逗号分隔的输入

Python 允许argparse nargs="+&引用;使用选项接受逗号分隔的输入,python,argparse,Python,Argparse,我想使用argparse的{choices}参数,但允许用户从选项中输入任意数量的项。例如,如果选项为[1,2,3],我希望以下选项有效: --arg 1 --arg 1,2 --arg 1,3 等等 然而,当使用nargs=“+”时,choices似乎不接受逗号分隔的输入。这有什么办法吗?我仍然希望强制执行传入的选项在我定义的选项集中,以错误检查奇怪的输入。这一行代码为您提供了所有可能的选项子集 from itertools import combinations, chain

我想使用argparse的{choices}参数,但允许用户从选项中输入任意数量的项。例如,如果选项为[1,2,3],我希望以下选项有效:

--arg 1
--arg 1,2
--arg 1,3
等等


然而,当使用nargs=“+”时,choices似乎不接受逗号分隔的输入。这有什么办法吗?我仍然希望强制执行传入的选项在我定义的选项集中,以错误检查奇怪的输入。

这一行代码为您提供了所有可能的选项子集

    from itertools import combinations, chain
    allsubsets = lambda n: list(chain(*[combinations(range(n), ni) for ni in range(n+1)]))

我同意-你会认为API会允许某人现在就这么做,对吗

不管怎样,我一直使用的解决方法如下:

p = argparse.ArgumentParser(description="Why doesn't argparse support list of args?")
parser.add_argument('--arg', type=str)
arg_list = parser.parse_args().args.split(",")
# if you wanted integers:
arg_list = [int(x) for x in arg_list]

AKA:接收字符串并自己处理。

以下是我实现这一点的方法:

import argparse
arg=argparse.ArgumentParser()
arg.add_argument( "--lista",  nargs="*", type=int, default=[1, 2, 3], )

args = arg.parse_args()
print("lista: {0}" .format(args.lista))
一些跑步

1455:~/mypy$ python stack49824248.py --arg 1 
['stack49824248.py', '--arg', '1']
Namespace(arg=[1])

1455:~/mypy$ python stack49824248.py --arg 1 3 2 1
['stack49824248.py', '--arg', '1', '3', '2', '1']
Namespace(arg=[1, 3, 2, 1])

1456:~/mypy$ python stack49824248.py --arg 1,2
['stack49824248.py', '--arg', '1,2']
usage: stack49824248.py [-h] [--arg {1,2,3} [{1,2,3} ...]]
stack49824248.py: error: argument --arg: invalid int value: '1,2'
shell与解释器一起在空格上分割输入,并在
sys.argv
中提供字符串列表。这就是
解析器处理的内容

使用
+
--arg
操作接受字符串列表(到结束或下一个标志)。每个字符串都通过
类型
函数传递,并将结果与
选项
(如果提供)进行比较。在本例中,
type
int
,因此选项也可以是整数。如果没有
类型
选项
必须是
['1','2','3']

如果我将参数更改为:

parser.add_argument('--arg', nargs='+', choices=['1','2','3','1,2','2,3'])
它将接受一些带有逗号的字符串:

1456:~/mypy$ python stack49824248.py --arg 1
['stack49824248.py', '--arg', '1']
Namespace(arg=['1'])
1505:~/mypy$ python stack49824248.py --arg 1,2
['stack49824248.py', '--arg', '1,2']
Namespace(arg=['1,2'])
1505:~/mypy$ python stack49824248.py --arg 1,2,3
['stack49824248.py', '--arg', '1,2,3']
usage: stack49824248.py [-h] [--arg {1,2,3,1,2,2,3} [{1,2,3,1,2,2,3} ...]]
stack49824248.py: error: argument --arg: invalid choice: '1,2,3' (choose from '1', '2', '3', '1,2', '2,3')
我没有包括“1,2,3”选项,所以它拒绝了。还要注意,我删除了
int
类型,因为
int('1,2')
将失败

因此,如果您需要接受“1,2,3”,请在解析后进行您自己的拆分和选择测试(或者可能作为自定义
Action
类)


列表必须用逗号分隔吗?标准的
argparse
格式是空格分隔的:嘿,对不起,我实际上稍微改变了我的问题。我想强制使用我最初没有提到的“选择”——关于如何使用它的任何想法?你需要使用选择吗?为什么不使用一个集合,然后检查结果呢?我喜欢choices提供的CLI,如果用户输入了错误的选项,它会向用户提供反馈。老实说,我认为我倾向于不使用逗号分隔的输入:p这很公平。我想你应该接受@toheedNiaz的回答:)
1456:~/mypy$ python stack49824248.py --arg 1
['stack49824248.py', '--arg', '1']
Namespace(arg=['1'])
1505:~/mypy$ python stack49824248.py --arg 1,2
['stack49824248.py', '--arg', '1,2']
Namespace(arg=['1,2'])
1505:~/mypy$ python stack49824248.py --arg 1,2,3
['stack49824248.py', '--arg', '1,2,3']
usage: stack49824248.py [-h] [--arg {1,2,3,1,2,2,3} [{1,2,3,1,2,2,3} ...]]
stack49824248.py: error: argument --arg: invalid choice: '1,2,3' (choose from '1', '2', '3', '1,2', '2,3')
In [16]: [(int(x) in [1,2,3]) for x in '1,2,3'.split(',')]
Out[16]: [True, True, True]
In [17]: [(int(x) in [1,2,3]) for x in '1,2,4'.split(',')]
Out[17]: [True, True, False]
In [18]: [(int(x) in [1,2,3]) for x in '1,a,4'.split(',')]
....
ValueError: invalid literal for int() with base 10: 'a'