![](/img/trans.png)
[英]Python Argparse: how to make an argument required if and only if one flag is given?
[英]How to make Python argparse accept a "-a" flag in place of the positional argument?
我正在使用 argparse 编写 Python 程序。 我有一个 ID 值的参数。 用户可以在程序中指定要处理的 ID 值。 或者他们可以指定 -a 来指定应该处理所有 ID。
因此,以下两项都应该有效:
myprog 5
myprog -a
但是如果你没有指定一个特定的 ID,那么 -a 是必需的,它应该抛出一个错误。
我玩过一个相互排斥的群体:
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-a', action='store_true', help=argparse.SUPPRESS)
group.add_argument("ID", action='store', nargs='?')
哪个有效,但我解析的参数最终是两个参数:
{'a': True, 'ID': None}
如果我尝试在此之后添加一个类似的组,请说另一个参数“max”可以是最大值或 -i 表示忽略最大值:
group2 = parser.add_mutually_exclusive_group(required=True)
group2.add_argument('-i', action='store_true', help=argparse.SUPPRESS)
group2.add_argument("max", action='store', nargs='?')
然后,如果我尝试解析参数 ['-a', '2'] 它会抛出一个错误说:
usage: args_exclusive_group.py [-h] [ID] [max]
args_exclusive_group.py: error: argument ID: not allowed with argument -a
因为它将 2 视为 ID 而不是最大值。 是否有一些我遗漏的非常简单的东西,它只允许指定的位置参数(ID 或 max)也接受一个恰好“看起来像”可选的字符串,因为它以“-”开头?
如果您想将其保留为 2 个位置参数,一种方法可能是将-a
和-i
标志封装在它们各自的参数中并进行一些后处理。 问题在于argparse
会自动考虑以-
开头的字符串作为参数:
位置参数只能以
-
开头,如果它们看起来像负数并且解析器中没有看起来像负数的选项。
因此,如果您将关键字更改为all
和ign
,则可以执行以下操作:
parser = argparse.ArgumentParser()
parser.add_argument("ID")
parser.add_argument("max")
args = parser.parse_args()
if args.ID == 'all':
print("processing all")
elif args.ID.isdigit():
print(f"processing {args.ID}")
else:
parser.error("ID must be a number or 'all' to use all IDs")
if args.max == 'ign':
print("ignoring max")
elif args.max.isdigit():
print(f"max is {args.max}")
else:
parser.error("max must be a number or 'ign' to disable max")
一些运行示例将是:
>>> tests.py 5 ign
processing 5
ignoring max
>>> tests.py all 7
processing all
max is 7
>>> tests.py blah 7
tests.py: error: ID must be a number or 'all' to use all IDs
>>> tests.py 5 blah
tests.py: error: max must be a number or 'ign' to disable max
如果你真的必须使用-a
和-i
:
您可以插入伪参数
'--'
,它告诉parse_args()
之后的所有内容都是位置参数
只需将解析行更改为:
import sys
...
args = parser.parse_args(['--'] + sys.argv[1:])
最简单的方法是只有一个位置参数,其值要么是像all
这样的特殊标记,要么是特定进程的编号。 您可以使用自定义类型处理此问题。
def process_id(s):
if s == "all":
return s
try:
return int(s)
except ValueError:
raise argparse.ArgumentTypeError("Must be 'all' or an integer")
p = argparse.ArgumentParser()
p.add_argument("ID", type=process_id)
args = p.parse_args()
if args.ID == "all":
# process everything
else:
# process just args.ID
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.