如何根据 Python 中的位置参数与 argparse 的组合设置不同的选项?

Posted

技术标签:

【中文标题】如何根据 Python 中的位置参数与 argparse 的组合设置不同的选项?【英文标题】:How to set different options based on combination of positional arguments in Python with argparse? 【发布时间】:2021-06-24 00:26:59 【问题描述】:

我正在尝试学习如何使用 argparse。我正在编写一个带有两个位置参数的程序,比如说ARG1ARG2,我想根据这两个位置参数的组合添加一些选项。

界面如下所示:

          D
          C
          B     B
          A     A
          ^     ^
          |     |
app.py <ARG1> <ARG2> --opt1 --opt2 --opt3 --opt4

第一个位置参数ARG1 将有4 个不同的选项,第二个位置参数ARG2 将有两个不同的选项。 基于这两个位置参数的组合,我想指定不同的选项。

例如,当用户输入app.py A B时,我只需要--opt1 --opt2。有些组合可能根本不使用某些选项。

我认为subparsers 是可行的方法,但我没有设法让它发挥作用。

我该怎么做?

【问题讨论】:

“子解析器”是一种positional,但只能有一个。但您的位置可能每个都有choices。解析后必须测试与选项的交互。 【参考方案1】:

由于argparse 旨在以任何顺序处理optionals,因此强制交互很尴尬。子解析器提供一些控制,但只能有一个(除非您定义子解析器的子解析器)。

我认为最简单的方法是用choices 和所有的可选项定义2 个位置,并在解析后进行任何“必需”检查:

In [20]: parser = argparse.ArgumentParser()
In [21]: parser.add_argument('arg1', choices=['A','B','C','D']);
In [22]: parser.add_argument('arg2', choices=['A','B']);
In [23]: parser.add_argument('--opt1');
In [24]: parser.add_argument('--opt2');

In [26]: args = parser.parse_args('--opt2 foo C A'.split())
In [27]: print(args)
Namespace(arg1='C', arg2='A', opt1=None, opt2='foo')

一个可能的测试:

In [29]: if args.arg1=='C' and args.arg2=='A' and args.opt1 is None:
    ...:     parser.error('--opt1 is required with C and A')
    ...: 
usage: ipython3 [-h] [--opt1 OPT1] [--opt2 OPT2] A,B,C,D A,B
ipython3: error: --opt1 is required with C and A

请记住,在使用和帮助中很难描述条件交互。要求optional 的替代方法是给它一个合理的默认值。这样,用户是否给出值都无关紧要。但是在上面的测试中,我是依赖默认的defaultNone

用法首先显示optionals,在命令行中optionals 可以按顺序出现,相对于自身和positionals

【讨论】:

【参考方案2】:

不确定我是否完全理解您的要求,但看看这个示例是否对您有帮助:

from argparse import ArgumentParser

parser = ArgumentParser()
subparsers = parser.add_subparsers(help="sub-commands")

a_parser = subparsers.add_parser("ARG1")

a_parser.add_argument("-1", "--opt1", action="store_true", required=False)
a_parser.add_argument("-2", "--opt2", action="store_true", required=False)
a_parser.add_argument("-3", "--opt3", action="store_true", required=False)
a_parser.add_argument("-4", "--opt4", action="store_true", required=False)

subparsers2 = a_parser.add_subparsers(help="ARG1-ARG2 sub-commands")

ab_parser = subparsers2.add_parser("ARG2")

ab_parser.add_argument("-1", "--opt1", action="store_true", required=False)
ab_parser.add_argument("-2", "--opt2", action="store_true", required=False)

b_parser = subparsers.add_parser("ARG2")

b_parser.add_argument("-3", "--opt3", action="store_true", required=False)
b_parser.add_argument("-4", "--opt4", action="store_true", required=False)

argument = parser.parse_args()

输出:

± % python recovery_tools/test.py ARG1 --help                                                 
usage: test.py ARG1 [-h] [-1] [-2] [-3] [-4] ARG2 ...

positional arguments:
  ARG2      ARG1-ARG2 sub-commands

optional arguments:
  -h, --help  show this help message and exit
  -1, --opt1
  -2, --opt2
  -3, --opt3
  -4, --opt4
± % python recovery_tools/test.py ARG1 ARG2 --help                                            
usage: test.py ARG1 ARG2 [-h] [-1] [-2]

optional arguments:
  -h, --help  show this help message and exit
  -1, --opt1
  -2, --opt2
± % python recovery_tools/test.py ARG2 --help                                                 
usage: test.py ARG2 [-h] [-3] [-4]

optional arguments:
  -h, --help  show this help message and exit
  -3, --opt3
  -4, --opt4
(new-recovery-tools-env)

【讨论】:

以上是关于如何根据 Python 中的位置参数与 argparse 的组合设置不同的选项?的主要内容,如果未能解决你的问题,请参考以下文章

Python中的参数是如何传递的?

如何根据鼠标点击位置参数触发Javascript中的事件?

python函数中的位置参数默认参数关键字参数可变参数区别

如何根据python中列中的变量位置计算行数

如何根据 Python 中的子类类型定义基类参数?

Python的位置参数、默认参数、关键字参数、可变参数区别