【问题标题】:python: mutually exclusive positional argumentspython:互斥位置参数
【发布时间】:2017-01-03 23:33:31
【问题描述】:

我希望我的程序接受互斥的位置参数,要显示为一组参数的用法。
目前我只能实现其中之一,但不能同时实现...

这是我目前拥有的:

def parse_arguments():
    arg_parser = argparse.ArgumentParser(description = 'Project Builder')

    query_parser = arg_parser.add_argument_group('query', "Query current state")
    build_parser = arg_parser.add_argument_group('build', "Build project")

    # query arguments
    query_parser.add_argument('-s', '--servers',
                 action   = 'store_true',
                 required = False,
                 help     = 'Display available servers')

    query_parser.add_argument('-u', '--users',
                 action   = 'store_true',
                 required = False,
                 help     = 'Display current users')



    # build arguments
    build_parser.add_argument('-f', '--force',
                 action   = 'store',
                 required = False,
                 metavar  = 'SERVER_NAME',
                 help     = 'Force build on SERVER_NAME')

    build_parser.add_argument('-c', '--clean',
                 action   = 'store_true',
                 required = False,
                 help     = 'Clean repo before build')

    build_parser.add_argument('-v', '--verbosity',
                 action   = 'store_true',
                 required = False,
                 help     = 'Print stderr to console')

    build_parser.add_argument('-p', '--project',
                 action   = 'store',
                 required = True,
                 metavar  = 'project_A|project_B|project_C',
                 type     = project_name,
                 help     = 'Project to build (required)')

    return vars(arg_parser.parse_args())


args = parse_arguments()

这给出了以下内容:

usage: test.py [-h] [-s] [-u] [-f SERVER_NAME] [-c] [-v] -p
               project_A|project_B|project_C

Project Builder

optional arguments:
  -h, --help            show this help message and exit

query:
  Query current state

  -s, --servers         Display available servers
  -u, --users           Display current users

build:
  Build project

  -f SERVER_NAME, --force SERVER_NAME
                        Force build on SERVER_NAME
  -c, --clean           Clean repo before build
  -v, --verbosity       Print stderr to console
  -p project_A|project_B|project_C, --project project_A|project_B|project_C
                        Project to build (required)

但我真正想要的是 querybuild 是两个互斥的位置参数。

我尝试如下使用子解析器:

def parse_arguments():
    arg_parser = argparse.ArgumentParser(description = 'Project Builder')
    command_parser = arg_parser.add_subparsers(help = "Command")

    query_parser = command_parser.add_parser('query', help = "Query current state")
    build_parser = command_parser.add_parser('build', help = "Build project")

    # query arguments
    query_parser.add_argument('-s', '--servers',
                 action   = 'store_true',
                 required = False,
                 help     = 'Display available servers')

    query_parser.add_argument('-u', '--users',
                 action   = 'store_true',
                 required = False,
                 help     = 'Display current users')



    # build arguments
    build_parser.add_argument('-f', '--force',
                 action   = 'store',
                 required = False,
                 metavar  = 'SERVER_NAME',
                 help     = 'Force build on SERVER_NAME')

    build_parser.add_argument('-c', '--clean',
                 action   = 'store_true',
                 required = False,
                 help     = 'Clean repo before build')

    build_parser.add_argument('-v', '--verbosity',
                 action   = 'store_true',
                 required = False,
                 help     = 'Print stderr to console')

    build_parser.add_argument('-p', '--project',
                 action   = 'store',
                 required = True,
                 metavar  = 'project_A|project_B|project_C',
                 type     = project_name,
                 help     = 'Project to build (required)')

    return vars(arg_parser.parse_args())

但这会产生以下结果:

usage: test.py [-h] {query,build} ...

Project Builder

positional arguments:
  {query,build}  Command
    query        Query current state
    build        Build project

optional arguments:
  -h, --help     show this help message and exit

我想要的是上述两种尝试的结合,即:

usage: test.py [-h] {query,build} ...

Project Builder

optional arguments:
  -h, --help            show this help message and exit

query:
  Query current state

  -s, --servers         Display available servers
  -u, --users           Display current users

build:
  Build project

  -f SERVER_NAME, --force SERVER_NAME
                        Force build on SERVER_NAME
  -c, --clean           Clean repo before build
  -v, --verbosity       Print stderr to console
  -p project_A|project_B|project_C, --project project_A|project_B|project_C
                        Project to build (required)

其中querybuild 是互斥的。
我知道ArgumentParser.add_mutually_exclusive_group(required=False) 方法,但使用它并没有帮助实现我想要的,因为1)使用它时参数必须是可选的,2)usage 格式不是我想要的。

【问题讨论】:

    标签: python argparse


    【解决方案1】:

    在第一种情况下,您可以给-p 选择

    build_parser.add_argument('-p', '--project',
                 action   = 'store',    # default
                 required = True,
                 choices  = ['project_A','project_B','project_C'],
                 # type     = project_name,    # doesn't make sense
                 help     = 'Project to build (required)')
    

    或作为一个位置

    build_parser.add_argument('project',
                 choices  = ['project_A','project_B','project_C'],
                 help     = 'Project to build')
    

    type 必须是一个函数,可以将字符串转换为您想要的东西,例如int('1')float('12.343')

    子解析器的使用类似。对于主解析器,子解析器参数只是一个带有选择的位置。但是采取的行动是将其余参数的解析委托给子解析器。

    两个相互排斥的位置没有逻辑意义

     `[foo | bar]`
    

    仅根据位置无法判断您是将字符串分配给foo 还是bar。但是您有兴趣根据值分配值,或者更确切地说,将值限制为一组选择。

    如果不仔细查看,您的子解析器代码看起来是正确的,并且应该根据需要解析输入。你测试过吗?

    子解析器的帮助显示并不像它应该的那样灵活,但重新设计它需要相当多的工作(关于这个有一些问题)。当前设置是为主解析器和每个子解析器提供单独的帮助显示。没有内置的综合帮助显示。

    【讨论】:

    • type = project_name 确实有意义,因为project_name 是一个函数名称(检查项目名称是否正确的验证器)。我猜“两个互斥位置参数”不是最好的选择......我想要的是git-like 行为,用户必须提供子命令(“互斥位置参数”是log ,status,show,branch,等等...)。
    • 如果project_name 是你自己的函数,那么它可能会做类似于choices 测试的事情。我习惯于张贴者滥用这个参数,认为它指定了一些对象类。我认为subparsers 应该在其他系统中充当子命令,尽管我确信它在细节上有所不同。
    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2019-09-22
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    相关资源
    最近更新 更多