何时argparse不报错缺少参数?
这个问题可能有个明显的答案,但我看了半天也没搞明白。这段代码是用旧版的Python写的,使用了argparse这个库。我最近没用过argparse,可能忘记了一些细节。
#test.py
def load_crossval_dataset(args):
schema, samplenum, permuted, search = args.schema, args.samplenum, args.permuted, args.search
print "schema", schema
print "samplenum", samplenum
print "permuted", permuted
print "search", search
import argparse
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
subparsers = parser.add_subparsers()
# create the parser for the "crossval" command
parser_crossval = subparsers.add_parser('crossval', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser_crossval.add_argument('schema', help='name of schema')
parser_crossval.add_argument("-n", "--samplenum", action="store", type=int, dest="samplenum", help="number of samples to do crossvalidation on")
parser_crossval.add_argument("-p", "--permuted", action="store_true", dest="permuted", help="permuted dataset", default=False)
parser_crossval.add_argument("-s", "--search", action="store_true", dest="search", help="model search", default=False)
parser_crossval.set_defaults(func=load_crossval_dataset)
args = parser.parse_args()
args.func(args)
我们可以这样调用它:
python test.py
usage: test.py [-h] {crossval} ...
test.py: error: too few arguments
现在这样调用:
python test.py crossval -h
usage: test.py crossval [-h] [-n SAMPLENUM] [-p] [-s] schema
positional arguments:
schema name of schema
optional arguments:
-h, --help show this help message and exit
-n SAMPLENUM, --samplenum SAMPLENUM
number of samples to do crossvalidation on (default: None)
-p, --permuted permuted dataset (default: False)
-s, --search model search (default: False)
现在这样调用:
python test.py crossval -n 1 -s True
schema True
samplenum 1
permuted False
search True
问题是:为什么argparse没有报错说缺少schema
这个参数,反而把它设置成了True
呢?
2 个回答
选项 -s
不需要额外的参数(像 store_const
、store_true
和 store_false
这些操作都不需要参数——这个在说明文档里应该更清楚一些)。所以在命令 python test.py crossval -n 1 -s True
中,True
实际上是 crossval
的一个位置参数,而不是 -s
的参数;因此它被当作 schema
的值。
而命令 python test.py crossval -n 1 -s
则会正确地提示缺少 test.py crossval
的参数。
简单来说,-s
这个选项是一个布尔值,也就是说它的存在就代表“真”,而不需要额外的参数。所以当你输入 python test.py crossval -n 1 -s True
时,True
被当作模式参数来处理,因为 -s
这个开关本身不需要值。
其实,从帮助文本中的用法说明就能看出这一点:
usage: test.py crossval [-h] [-n SAMPLENUM] [-p] [-s] schema
这里的 [-s]
表示这是一个不带参数的选项,而 -n
则需要一个参数,所以它的格式是 [-n SAMPLENUM]
。
补充说明:
这种行为在 Python 2.7 的 argparse 文档 中有说明。我推测你在例子中使用的就是这个版本,因为你用的是语句形式而不是函数形式的 print
。引用文档第15.4.3.2节:
'store_true' 和 'store_false' - 这两者是 'store_const' 的特殊情况,分别用于存储值 True 和 False。此外,它们分别创建默认值 False 和 True。