Python的argparse默认值不起作用。

3
我是使用Python 2.7.13版本。
我的目标是有三个可能的参数,如果用户没有给出参数,则设置默认值:
parser.add_argument("-r", nargs=3, default=(0, 1000, 50), type=int, help="Useful help text")

这对我不起作用,而且我找不到任何地方说明是否可以像上面那样使用默认值。

当以 program.py -r 运行时,我会收到一个错误:期望3个参数。

但我也尝试完全删除 nargs 并只有一个默认值:

parser.add_argument("-r", default=100)

很奇怪,这也不起作用。它需要至少一个参数...

有人理解吗?


如果你使用 program.py -r 命令执行,argparse 会期望一些参数,如果你跳过 -r 标志,它将使用默认值。 - rammelmueller
4个回答

4

我将用一个 Ipython 交互式会话演示 argparsedefault 的正常行为。

In [32]: parser = argparse.ArgumentParser()

定义3个动作:

In [33]: parser.add_argument('-r', nargs=3, type=int, default=(1,2,3));
In [35]: parser.add_argument('-f', default='DEFAULT');
In [37]: parser.add_argument('-g', nargs='?', default='DEFAULT', const='const');

help是一个命令。需要注意的是所有的操作都有[],表示它们是可选的:

In [39]: parser.print_help()
usage: ipython3 [-h] [-r R R R] [-f F] [-g [G]]

optional arguments:
  -h, --help  show this help message and exit
  -r R R R
  -f F
  -g [G]

如果没有任何参数调用,则所有默认值均出现在args命名空间中。
In [40]: parser.parse_args([])  # e.g python myprog.py
Out[40]: Namespace(f='DEFAULT', g='DEFAULT', r=(1, 2, 3))

使用-r并提供3个数字(如nargs所指定的)

In [41]: parser.parse_args('-r 4 5 6'.split())  
Out[41]: Namespace(f='DEFAULT', g='DEFAULT', r=[4, 5, 6])

请指定其他标志之一。注意其余默认值。

In [42]: parser.parse_args('-f other'.split())  
Out[42]: Namespace(f='other', g='DEFAULT', r=(1, 2, 3))

-g带有nargs='?'的选项还有另一个选项。它可以不带参数给出。在这种情况下,它会获取const值。

In [43]: parser.parse_args('-f other -g'.split())  
Out[43]: Namespace(f='other', g='const', r=(1, 2, 3))
In [44]: parser.parse_args('-f other -g more'.split())  
Out[44]: Namespace(f='other', g='more', r=(1, 2, 3))
nargs=3 没有三个选项的设置。你要么提供三个值,要么不使用-r。如果需要区分 1)没有 r 标志,2)带参数的 r 标志,以及 3)带有三个参数的 r 标志,我建议将功能拆分为两种操作,一种是“store_true”,另一种是接受三个值的操作。argparse 中的默认值可能会很复杂,有多种设置方式,字符串和非字符串值之间存在差异,甚至还有一种抑制默认值的方式。但我已经展示了基本的行为。

1

如果您不使用默认值,只需要调用参数 -r。如果调用该参数,则还必须传递一个值(或者您在nargs中定义的多个值)。

尝试只调用 program.py。


好的,但是如果我想无论如何都能使用-r怎么办?由于我还有其他标志,我希望能够使用带或不带参数的-r。当然,如果没有给出参数,则具有默认值。这可能吗? - AltoBalto
-r 没有参数时应该做什么? - hpaulj
当您调用没有标志的program.py时,意味着您想要所有标志的默认值。如果不是这样,您应该说一下 ;) 因此,如果您想使用带有默认值的-r,请不要提及它,并让argarse静默地分配其默认值。如果由于某种原因您必须提到-r,请显式地传递其默认值。 - user5725006
抱歉,我应该更具体地说明:) 我必须提到-r,因为它执行特定的功能。目的是为了让用户有可能添加范围,例如-r 0 1000,但如果排除此范围,则需要将该范围设置为默认值。那么我如何明确传递其默认值呢? - AltoBalto
当您在没有标志的情况下调用program.py时,默认情况下r将设置为100。如果由于某种神秘原因您需要在控制台中显式输入-r,则可以通过调用program.py -r 100来调用默认值。或者,如果您需要传递一个列表,则执行 program.py -r 0 1000 50。如果您还有另一个标志,您可以调用 program.py -r 0 1000 50 -other_flag 'value'。 - user5725006

0

为什么不使用argv

示例:

import sys

def main(first=1, second=2, third=3):
    print first,second,third

if __name__ == '__main__':
    main(*sys.argv[1:])       # notice the * before sys.argv[1:]

您可以在控制台中使用不同数量的参数测试执行文件:

python myprogram.py          # will print 1 2 3
python myprogram.py 7        # will print 7 2 3
python myprogram.py 7 8      # will print 7 8 3
python myprogram.py 7 8 9    # will print 7 8 9

在 sys.argv 前面的 * 代表什么? - AltoBalto

0

通过您的示例,您可以在不使用-r标志的情况下调用应用程序,这将导致默认值。如果您想自己指定值,则必须全部给出。

如果您想独立输入它们,可以尝试类似以下的方法:

# script.py
import argparse

def main1():
    parser = argparse.ArgumentParser()
    parser.add_argument("-r", nargs=3, default=(0, 1000, 50), type=int,
                        help="Useful help text")
    args = parser.parse_args()
    print(args)

def main2():
    parser = argparse.ArgumentParser()
    parser.add_argument("-r1", type=int, default=0, help="...")
    parser.add_argument("-r2", type=int, default=1000, help="...")
    parser.add_argument("-r3", type=int, default=50, help="...")
    args = parser.parse_args()
    print(args)

if __name__ == "__main__":
    main1()
    #main2()

你可以这样调用你的实现(main1):

$ python script.py
Namespace(r=(0, 1000, 50))
$ python script.py -r 1 2 3
Namespace(r=[1, 2, 3])
$ python script.py -r 1
usage: args.py [-h] [-r R R R]
args.py: error: argument -r: expected 3 arguments

使用单独的参数,您的调用可能会像这样(main2):

$ python script.py -r1 1 -r2 2 -r3 3
Namespace(r1=1, r2=2, r3=3)
$ python script.py -r1 1
Namespace(r1=1, r2=1000, r3=50)
$ python script.py -r2 2
Namespace(r1=0, r2=2, r3=50)
$ python script.py -r3 3
Namespace(r1=0, r2=1000, r3=3)

如果您想更改所有值,这可能会更加冗长,但它会给您更多的灵活性。我认为您甚至可以使用互斥组结合这两种方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接