何时argparse不报错缺少参数?

1 投票
2 回答
1089 浏览
提问于 2025-04-18 10:43

这个问题可能有个明显的答案,但我看了半天也没搞明白。这段代码是用旧版的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 个回答

1

选项 -s 不需要额外的参数(像 store_conststore_truestore_false 这些操作都不需要参数——这个在说明文档里应该更清楚一些)。所以在命令 python test.py crossval -n 1 -s True 中,True 实际上是 crossval 的一个位置参数,而不是 -s 的参数;因此它被当作 schema 的值。

而命令 python test.py crossval -n 1 -s 则会正确地提示缺少 test.py crossval 的参数。

1

简单来说,-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。

撰写回答