如何在Python的argparse中对同一组参数调用两次parse_args()?

时间:2015-09-02 19:57:33

标签: python argparse

简化测试用例: 我有一个带有两个参数的脚本。第一个是整数列表。第二个是一个整数,必须包含在第一个参数的整数集中。

例如:

$ python argtest.py --valid_nums 1 2 3 --num 2

应该有效,但是:

$ python argtest.py --valid_nums 1 2 3 --num 4

不应该有效,因为num不是in valid_nums。但是,我遇到了一些困难(阅读:我怀疑它比它的价值更麻烦,但我真的希望它可以工作)实现这个功能。

实施尝试:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--valid_nums',
                    type=int,
                    nargs='+')

args = parser.parse_args()
print "Numbers: ", args.valid_nums


parser.add_argument('--num',
                    type=int,
                    choices=args.valid_nums)

args = parser.parse_args()
print args

实际输出:

$ python argtesttest.py --valid_nums 1 2 3 --num 2
usage: argtesttest.py [-h] [--valid_nums VALID_NUMS [VALID_NUMS ...]]
argtesttest.py: error: unrecognized arguments: --num 2

期望的输出:

$ python argtesttest.py --valid_nums 1 2 3 --num 2
Namespace(num=2, valid_nums=[1, 2, 3])

现在,(我认为)这里的问题是我在调用parse_args()之后无法向解析器添加新参数,这会产生关于无法识别的参数的错误,但是我想不出一个绕过它。有没有办法打破论证的处理,使其不是一次性的?

显然,如果我只调用parse_args()一次并自己处理容器成员资格检查,这将是非常简单的事情,但我希望使用argparse构建的“原生”工作-in错误检查。

有什么想法吗?

2 个答案:

答案 0 :(得分:6)

您需要使用parser.parse_known_args()而不是parser.parse_args(),或者在调用parse_args()之前将所有参数添加到解析器。

parse_args()需要理解sys.argv中的所有当前参数,这些参数在首次解析时已经包含--num,因此是例外。

答案 1 :(得分:2)

您可以使用namespace和parse_known_args来完成,并在结尾处调用parse_args

class UserNamespace(object):
    pass
user_namespace = UserNamespace()

p = argparse.ArgumentParser() 
p.add_argument('-c', '--config', dest='config', default='')
p.parse_known_args(namespace=user_namespace)
if user_namespace.config == '':
    p.add_argument('-w', '--whatever', dest='whatever', default='')

parsed_args = p.parse_args(namespace=user_namespace)

具体案例:

num.py:

import argparse
class UserNamespace(object):
    pass
user_namespace = UserNamespace()

parser = argparse.ArgumentParser()
parser.add_argument('--valid_nums', dest='valid_nums',
                    type=int,
                    nargs='+')

parser.parse_known_args(namespace=user_namespace)

parser.add_argument('--num',
                    type=int,
                    choices=user_namespace.valid_nums)

args = parser.parse_args(namespace=user_namespace)

print "Numbers: ", user_namespace.valid_nums

所以你打电话:

$python num.py --valid_nums 1 2 3 --num 2  
Numbers:  [1, 2, 3]

$python num.py --valid_nums 1 2 3 --num 4  
usage: num.py [-h] [--valid_nums VALID_NUMS [VALID_NUMS ...]] [--num {1,2,3}]
num.py: error: argument --num: invalid choice: 4 (choose from 1, 2, 3)

参考: argparse namespace
argparse parse_known_args

再见!

2017年3月4日更新 最好实例化UserNamespace,或其他功能(如add_subparsers)无法正常工作。