我有一组参数可以在逻辑上分为两组:
A1
,A2
,A3
等I1
,I2
,I3
等程序启动时至少需要其中一个参数,但“信息”参数可以与“动作”参数一起使用。所以
我找不到如何使用argparse来做到这一点。我知道add_mutually_exclusive_group
及其required
参数,但我不能在“动作”上使用它,因为它实际上并不是必需的。当然,我可以在argparse之后添加一个条件来手动检查我的规则,但它看起来像是一个黑客。 argparse可以这样做吗?
编辑:对不起,这里有一些例子。
# Should pass
--A1
--I1
--A1 --I2
--A2 --I1 --I2
# Shouldn't pass
--A1 --A2
--A1 --A2 --I1
答案 0 :(得分:4)
There's nothing hacky about verifying arguments after they've been parsed. Just collect them all in a single set, then confirm that it is not empty and contains at most one action.
[02/12/2016 19:48:35 > 686340: SYS INFO] Detected WebJob file/s were updated, refreshing WebJob
[02/12/2016 19:48:35 > 686340: SYS INFO] Status changed to Stopping
[02/12/2016 19:48:35 > 686340: SYS INFO] Status changed to Stopped
[02/12/2016 19:48:35 > 686340: SYS INFO] Status changed to Starting
[02/12/2016 19:48:35 > 686340: SYS INFO] Run script 'Timbo.Azure.Worker.exe' with script host - 'WindowsScriptHost'
[02/12/2016 19:48:35 > 686340: SYS INFO] Status changed to Running
[02/12/2016 19:48:35 > 686340: SYS ERR ] Job failed due to exit code -2146232576
[02/12/2016 19:48:35 > 686340: SYS INFO] Process went down, waiting for 60 seconds
[02/12/2016 19:48:35 > 686340: SYS INFO] Status changed to PendingRestart
[02/12/2016 19:49:36 > 686340: SYS INFO] Run script 'Timbo.Azure.Worker.exe' with script host - 'WindowsScriptHost'
[02/12/2016 19:49:36 > 686340: SYS INFO] Status changed to Running
[02/12/2016 19:49:36 > 686340: SYS ERR ] Job failed due to exit code -2146232576
[02/12/2016 19:49:36 > 686340: SYS INFO] Process went down, waiting for 60 seconds
[02/12/2016 19:49:36 > 686340: SYS INFO] Status changed to PendingRestart
答案 1 :(得分:2)
我错过了什么,或者你只是想要:
import argparse
import os
def main():
parser = argparse.ArgumentParser()
actions = parser.add_mutually_exclusive_group()
actions.add_argument("-A1", action="store_true")
actions.add_argument("-A2", action="store_true")
actions.add_argument("-A3", action="store_true")
low = int(os.environ.get('LOWER_BOUNDS', 0))
high = int(os.environ.get('UPPER_BOUNDS', 3)) + 1
infos = parser.add_argument_group()
for x in range(low, high):
infos.add_argument("-I" + str(x), action="store_true")
args = parser.parse_args()
if not any(vars(args).values()):
parser.error('No arguments provided.')
print args
if __name__ == '__main__':
main()
输出:
$ python test.py
usage: test.py [-h] [-A1 | -A2 | -A3] [-I0] [-I1] [-I2] [-I3]
test.py: error: No arguments provided.
$ python test.py -A1
Namespace(A1=True, A2=False, A3=False, I1=False, I2=False, I3=False)
$ python test.py -A1 -A2
usage: test.py [-h] [-A1 | -A2 | -A3] [-I1] [-I2] [-I3]
test.py: error: argument -A2: not allowed with argument -A1
$ python test.py -A1 -I1
Namespace(A1=True, A2=False, A3=False, I1=True, I2=False, I3=False)
$ python test.py -A1 -I1 -I2
Namespace(A1=True, A2=False, A3=False, I1=True, I2=True, I3=False)
$ python test.py -A1 -I1 -I2 -I3
Namespace(A1=True, A2=False, A3=False, I1=True, I2=True, I3=True)
$ UPPER_BOUNDS=40 python test.py -A1 -I1 -I2 -I40
Namespace(A1=True, A2=False, A3=False, I0=False, I1=True, I10=False, I11=False, I12=False, I13=False, I14=False, I15=False, I16=False, I17=False, I18=False, I19=False, I2=True, I20=False, I21=False, I22=False, I23=False, I24=False, I25=False, I26=False, I27=False, I28=False, I29=False, I3=False, I30=False, I31=False, I32=False, I33=False, I34=False, I35=False, I36=False, I37=False, I38=False, I39=False, I4=False, I40=True, I5=False, I6=False, I7=False, I8=False, I9=False)
PS。我真的没有建议这种“无限制”-I#
方法......但这里有一个例子。
答案 2 :(得分:1)
mutually_exclusive_group
是一个简单的xor
逻辑测试。您可以定义2个单独的组,但它不提供跨组/跨组之间的任何工作方式。
我已经开发了一个补丁,允许更复杂的逻辑和嵌套组。测试逻辑并不是那么糟糕,但设计一个好的用户界面很棘手,就像创建一个有意义的usage
行一样。因此,增强可能永远不会出现生产。
解析后测试参数非常好。如果您无法区分具有默认值的属性和用户提供的属性,那么它变得棘手 - 因此默认的默认None
是最佳的。 argparse
主要是一个解析器,弄清楚用户想要什么。他们是否想要合法的东西(超出最简单的情况)是一个不同的问题。