如何根据位置参数的值设置argparse以排除可选参数
这个参数包含一个动作字段和一些可选的开关,这些开关可以改变动作的行为。
下面是argparse的代码示例:
parser=argparse.ArgumentParser()
parser.add-argument('action',metavar='action', choices=['analysis','report','update'],nargs='?', default='report')
parser.add-argument('-d',dest='delay',type=int, choices=range(1,10),default=1)
parser.add-argument('-v',dest='verbose',action='store-true',default=False)
parser.add-argument('-o',dest='offline',action='store-true',default=False)
parser.add-argument('-n',dest='names',required=False)
我想让开关选项 -o、-d、-v 只在动作为 report 时可用,而选项 -n 只在动作为 analysis 时可用。
我知道有一个互斥组的设置,但这个设置只是针对参数,而不是针对参数的值!
顺便问一下,argparse 支持组合选项吗,比如 -vo...???
1 个回答
首先:是的,像 -vo 这样的组合选项是支持的。
接下来谈谈如何切换动作:在你的 ArgumentParser 中添加一个子解析器正是你想要做的事情。可以查看文档中关于 15.4.5.1. 子命令 的部分,那里详细解释了相关内容,并且有示例。
编辑:我现在参考你在这篇帖子下的评论:如果你在程序调用时没有提供子命令参数,解析器通常会给你一个友好的提示,告诉你如何使用这个程序,然后以“参数太少”错误退出。我重写了你的代码来展示这一点。
test.py
import argparse
parser=argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='sub-command help')
parser_analysis = subparsers.add_parser('analysis', help='analysis help text')
parser_analysis.add_argument('-n',dest='names',required=False)
parser_report = subparsers.add_parser('report', help='report help text')
parser_report.add_argument('-d',dest='delay',type=int, choices=range(1,10),default=1)
parser_report.add_argument('-v',dest='verbose',action='store_true',default=False)
parser_report.add_argument('-o',dest='offline',action='store_true',default=False)
parser_update = subparsers.add_parser('update', help='update help text')
parser.parse_args()
现在来看一下用不同参数调用这个 test.py
的情况:
$python test.py
usage: test.py [-h] {analysis,report,update} ...
test.py: error: too few arguments
$python test.py -h
usage: test.py [-h] {analysis,report,update} ...
positional arguments:
{analysis,report,update}
sub-command help
analysis analysis help text
report report help text
update update help text
optional arguments:
-h, --help show this help message and exit
$python test.py report -h
usage: test.py report [-h] [-d {1,2,3,4,5,6,7,8,9}] [-v] [-o]
optional arguments:
-h, --help show this help message and exit
-d {1,2,3,4,5,6,7,8,9}
-v
-o
所以我认为唯一的问题是,当你调用 python test.py
而没有任何子命令时,程序会抛出一个错误。因此,我会做一些类似这样的事情:
try:
args=parser.parse_args()
except:
exit(0)
这样可以避免用户看到未处理的错误。这样你就能得到和 svn
命令一样的行为。
如果你想处理成执行一个默认的子命令,你需要做一些类似于这个帖子回答中提到的事情:
import sys
#...your parser definitions
if (len(sys.argv) < 2):
args = parser.parse_args(['update'])
else:
args = parser.parse_args()
如果 sys.argv
中的参数列表少于 2,这将解析一个命令 update
。为什么是 2?因为参数列表中的第一个参数总是你调用的程序,比如 test.py
。
问题是,你真的想要这样的行为吗?因为如果我可以随时调用 test.py
,就没有必要调用 test.py update
,所以用户可能会变得懒惰,根本不使用 test.py update
命令。此外,如果你以后想要不同的默认行为,比如 test.py
启动交互模式,习惯于调用 test.py
来更新的用户可能会感到困惑,或者他们使用你程序的脚本会出错。