【问题标题】:Implementing two positional arguments using argparse's `add_subparsers` method使用 argparse 的 `add_subparsers` 方法实现两个位置参数
【发布时间】:2012-08-31 13:07:04
【问题描述】:

我想在使用argparse 库的add_subparsers 方法而不使用关键字参数nargs 时获得以下功能:

$ python my_program.py scream Hello
You just screamed Hello!!
$ python my_program.py count ten
You just counted to ten.

我知道我可以这样做:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("cmd", help="Execute a command", action="store",
  nargs='*')
args = parser.parse_args()
args_list = args.cmd

if len(args.cmd) == 2:
    if args.cmd[0] == "scream":
        if args.cmd[1] == "Hello":
            print "You just screamed Hello!!"
        else:
            print "You just screamed some other command!!"

    elif args.cmd[0] == "count":
        if args.cmd[1]:
            print "You just counted to %s." % args.cmd[1]
        else:
            pass

    else:
        print "These two commands are undefined"

else:
    print "These commands are undefined"

但是当我执行 $ python my_program.py 时,我会丢失显示参数列表等的默认 arparse 文本。

我知道argparse 库的add_subparsers 方法可以处理多个位置参数,但我还没有找到让它正常工作的方法。谁能告诉我怎么做?

【问题讨论】:

    标签: python arguments command-line-arguments argparse


    【解决方案1】:
    import argparse
    
    def scream(args):
        print "you screamed "+' '.join(args.words)
    
    def count(args):
        print "you counted to {0}".format(args.count)
    
    parser = argparse.ArgumentParser()
    
    #tell the parser that there will be subparsers
    subparsers = parser.add_subparsers(help="subparsers")
    
    #Add parsers to the object that was returned by `add_subparsers`
    parser_scream = subparsers.add_parser('scream')
    
    #use that as you would any other argument parser
    parser_scream.add_argument('words',nargs='*')
    
    #set_defaults is nice to call a function which is specific to each subparser
    parser_scream.set_defaults(func=scream) 
    
    #repeat for our next sub-command
    parser_count = subparsers.add_parser('count')
    parser_count.add_argument('count')
    parser_count.set_defaults(func=count)
    
    #parse the args
    args = parser.parse_args()
    args.func(args)  #args.func is the function that was set for the particular subparser
    

    现在运行它:

    >python test.py scream Hello World!  #you screamed Hello World!
    >python test.py count 10             #you counted to 10
    

    【讨论】:

    • 当我执行$ python my_program 时,我得到usage: dummy.py [-h] {scream,count} ... my_program.py: error: too few arguments。知道如何在没有任何参数的情况下优雅地摆脱调用中的错误行吗?
    • @Bentley4 -- 当您添加子解析器时,您暗示其中一个应该被调用。如果你想让它做一些不同的事情,你可以提前弄乱sys.argv。 (if len(sys.argv) == 1: sys.exit()) 或if len(sys.argv) == 1: sys.argv.append('scream')...
    【解决方案2】:

    使用add_subparsers 时,您基本上是在创建嵌套解析器:

    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(help='sub-command help')
    
    parser_scream = subparsers.add_parser('scream', help='scream help')
    

    现在您有了一个 new 解析器对象,您可以在其中添加开关。 或者,可以再增加一层嵌套:

    scream_subparsers = parser_scream.add_subparsers(help='scream sub-command help')
    parser_scream_hello = scream_subparsers.add_parser('hello', help='scream hello help')
    

    这可以深入到您需要控制精确格式的程度。每个级别都提供帮助:

    >>> parser.print_help()
    usage: [-h] {scream} ...
    
    positional arguments:
      {scream}    sub-command help
        scream    scream help
    
    optional arguments:
      -h, --help  show this help message and exit
    >>> parser_scream.print_help()
    usage:  scream [-h] {hello} ...
    
    positional arguments:
      {hello}     scream sub-command help
        hello     scream hello help
    
    optional arguments:
      -h, --help  show this help message and exit
    >>> parser_scream_hello.print_help()
    usage: scream hello [-h]
    
    optional arguments:
      -h, --help  show this help message and exit
    

    您可以让每个端点调用一个函数,方法是在相关子解析器上使用 set_defaults(func=yourfunction),然后使用默认的 func 参数为当前参数调用所选函数:

    >>> def scream_hello(args):
    ...     print "You screamed hello!"
    ...
    >>> parser_scream_hello.set_defaults(func=scream_hello)
    >>> parser.parse_args(['scream', 'hello'])
    Namespace(func=<function scream_hello at 0x10bd73c80>)
    >>> args = parser.parse_args(['scream', 'hello'])
    >>> args.func(args)
    You screamed hello!
    

    【讨论】:

    • 我选择了 mgilson 的答案,因为我发现他的代码示例更容易理解。但是你给了一个很好的解释,谢谢!
    猜你喜欢
    • 2015-07-25
    • 1970-01-01
    • 2011-05-27
    • 2018-08-10
    • 2011-07-19
    • 2014-05-11
    • 2015-07-12
    • 2012-03-28
    • 2011-05-27
    相关资源
    最近更新 更多