如何在 Python 的 argparse 中对同一组参数调用 parse_args() 两次?
How to call parse_args() twice on the same set of arguments in Python's 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()
一次并自己处理容器成员资格检查,这将是非常微不足道的,但我想让它工作 'natively' 使用 argparse
的内置错误检查。
有什么想法吗?
您需要使用 parser.parse_known_args()
而不是 parser.parse_args()
,或者在调用 parse_args()
.
之前将所有参数添加到解析器
parse_args()
需要理解 sys.argv
中的所有当前参数,其中在第一次解析时已经包含 --num
,因此异常。
你可以用命名空间和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)无法正常工作。
简化测试用例: 我有一个带有两个参数的脚本。第一个是整数列表。第二个是必须包含在第一个参数的整数集中的单个整数。
例如:
$ 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()
一次并自己处理容器成员资格检查,这将是非常微不足道的,但我想让它工作 'natively' 使用 argparse
的内置错误检查。
有什么想法吗?
您需要使用 parser.parse_known_args()
而不是 parser.parse_args()
,或者在调用 parse_args()
.
parse_args()
需要理解 sys.argv
中的所有当前参数,其中在第一次解析时已经包含 --num
,因此异常。
你可以用命名空间和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)无法正常工作。