允许 argparse nargs="+" 接受带有选项的逗号分隔输入
Allow argparse nargs="+" to accept comma-separated input with choices
我想使用 argparse 的 {choices} 参数,但允许用户从选项中输入任意数量的项目。例如,如果选择是 [1,2,3],我希望以下内容有效:
--arg 1
--arg 1,2
--arg 1,3
等等
但是,使用 nargs="+" 时,选择似乎不接受以逗号分隔的输入。有没有办法解决?我仍然想强制传入的选项在我定义的选项集中,以对奇怪的输入进行错误检查。
这一行代码为您提供了所有可能的选择子集。
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]
又名:接收字符串并自行处理。
import argparse, sys
print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('--arg', nargs='+', choices=[1,2,3], type=int)
args = parser.parse_args()
print(args)
一些跑步
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
中提供字符串列表。这就是 parser
处理的内容。
对于 +
,--arg
操作接受字符串列表(到末尾或下一个标志)。每个字符串都通过 type
函数传递,并将结果与 choices
(如果提供)进行比较。在这种情况下,type
是 int
,因此选项也可以是整数。如果没有 type
,choices
就必须是 ['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
type
,因为 int('1,2')
会失败。
因此,如果您需要接受“1,2,3”,请在解析后进行自己的拆分和选择测试(或者可能作为自定义 Action
class)。
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'
我想使用 argparse 的 {choices} 参数,但允许用户从选项中输入任意数量的项目。例如,如果选择是 [1,2,3],我希望以下内容有效:
--arg 1
--arg 1,2
--arg 1,3
等等
但是,使用 nargs="+" 时,选择似乎不接受以逗号分隔的输入。有没有办法解决?我仍然想强制传入的选项在我定义的选项集中,以对奇怪的输入进行错误检查。
这一行代码为您提供了所有可能的选择子集。
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]
又名:接收字符串并自行处理。
import argparse, sys
print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('--arg', nargs='+', choices=[1,2,3], type=int)
args = parser.parse_args()
print(args)
一些跑步
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
中提供字符串列表。这就是 parser
处理的内容。
对于 +
,--arg
操作接受字符串列表(到末尾或下一个标志)。每个字符串都通过 type
函数传递,并将结果与 choices
(如果提供)进行比较。在这种情况下,type
是 int
,因此选项也可以是整数。如果没有 type
,choices
就必须是 ['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
type
,因为 int('1,2')
会失败。
因此,如果您需要接受“1,2,3”,请在解析后进行自己的拆分和选择测试(或者可能作为自定义 Action
class)。
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'