Python Argparse 子解析器

Posted

技术标签:

【中文标题】Python Argparse 子解析器【英文标题】:Python Argparse subparsers 【发布时间】:2018-12-31 20:47:45 【问题描述】:

我正在使用 Argparse 模块来解析命令行选项。我有一个主脚本,它调用下标 A 或下标 B。我现在有一个用于 A 和 B 的子解析器实例和主解析器实例,它应该包含有关 A 和 B 需要的变量的信息。比如:

def __init__(self):
    parser = argparse.ArgumentParser("Parser")
    parser.addArgument('--input') #this should be availabe for A and B

    subparsers = parser.add_subparsers('Description')
    A_parser = subparsers.add_parser(A)
    A_paser.add_argument('--a_option')

    B_parser = parser.add_subparser('Description')
    B_parser.add_arguemnt('--b_option')

    args = parser.parse_args()

但是如果我这样使用它,如果我没有在程序调用中指定 A 或 B,我只能通过 --input 选项更改 args.options。执行

program.py A --input ./

program.py --input ./ A

都失败了。

【问题讨论】:

【参考方案1】:

我认为您弄乱了 python 文档中的示例用法。我试图编辑您的代码示例,但我放弃了很多错别字。特别是add_subparsers()add_parser() 的用法混淆了。

代码的清理(和独立)版本如下所示:

import argparse


parser = argparse.ArgumentParser("Parser")
parser.add_argument('--input') #this should be available for A and B

subparsers = parser.add_subparsers(help='Description')
A_parser = subparsers.add_parser('A')
A_parser.add_argument('--a_option')

B_parser = subparsers.add_parser('B')
B_parser.add_argument('--b_option')

现在你可以打电话了

args = parser.parse_args(['--input', 'foo'])

还有

args = parser.parse_args(['--input', 'bar', 'A', '--a_option', 'a_option_arg'])

args = parser.parse_args(['--input', 'baz', 'B', '--b_option', 'b_option_arg'])

更新

在 cmets 中,您会问:

是否有可能我也可以为 --input 选项传递未知数量的参数,然后仍然有 A 选项?比如:program.py --input ./ ../ ../../ A -a_option

如果您想将未知数量的参数传递给--input 选项,您需要将nargs='*' 传递给--input 的参数定义。但是,您不能再使用AB 之类的标签来选择您的子解析器,因为这些将作为--input 的进一步参数。

在这种情况下,您可以求助于父解析器。使用父解析器,您可以将多个解析器的选项合并为一个:

import argparse


A_parser = argparse.ArgumentParser(add_help=False)
A_parser.add_argument('--a_option')

B_parser = argparse.ArgumentParser(add_help=False)
B_parser.add_argument('--b_option')

parser = argparse.ArgumentParser("Parser", parents=[A_parser, B_parser])
parser.add_argument('--input', nargs='*')  # this should be available for A and B

现在所有选项每次都可用:

args = parser.parse_args(['--input', 'foo'])
args = parser.parse_args(['--input', 'foo' , 'bar', '--a_option', 'a_option_arg'])
args = parser.parse_args(['--input', 'baz', '--b_option', 'b_option_arg'])

请注意,不再有“A”和“B”标签。通过选择A_parser 定义的选项之一来选择“A”。甚至可以同时使用两者:

args = parser.parse_args(['--input', 'foo' ,'--a_option', 'a_option_arg', '--b_option', 'b_option_arg'])

如果您不希望这样做,则需要对冲突参数实施检查。

【讨论】:

这仅在 --input 为 store_true 或后面有定义数量的参数时才有效。是否有可能 I 也可以为 --input 选项传递未知数量的参数,然后仍然有 A 选项?类似于:program.py --input ./ ../ ../../ A -a_option 主解析器无法判断 --input 的 args 何时停止而子解析器名称何时开始。它通过位置而不是值来检查这样的事情。

以上是关于Python Argparse 子解析器的主要内容,如果未能解决你的问题,请参考以下文章

带有所需子解析器的 Argparse

Python argparse:存储参数不匹配任何子解析器

带有通用子解析器命令的 Python argparse

如何从 Python 3 中的现有程序创建带有 argparse 的子解析器?

argparse 可选子解析器(用于 --version)

argparse 未正确处理子解析器中的缩写