gpt4 book ai didi

python - Argparse:将父解析器与子解析器混合

转载 作者:太空宇宙 更新时间:2023-11-03 15:04:09 24 4
gpt4 key购买 nike

我想编写一个简单的工具,它接受任意数量的输入文件并对每个文件执行一个操作。语法非常简单:

mytool operation input1 input2 ... inputN

其中一些操作可能需要额外的参数

mytool operation op_argument input1 input2 ... inputN 

除此之外,我希望用户能够指定是否应就地执行操作,并指定输出的目标目录。

mytool -t $TARGET --in-place operation op_argument input1 input2 input3

作为最后一个要求,我希望用户能够获得有关每个操作以及整个工具的使用的帮助。

这是我为所述工具设计参数解析器的尝试,以及一个最小的、完整的、可验证的示例:

#!/bin/env python

import argparse
from collections import namedtuple

Operations = namedtuple('Ops', 'name, argument, description')
IMPLEMENTED_OPERATIONS = {'echo': Operations('echo',
None,
'Echo inputs'),
'fancy': Operations('fancy',
'fancyarg',
'Do fancy stuff')}


if __name__ == "__main__":

# Parent parser with common stuff.
parent = argparse.ArgumentParser(add_help=False)
parent.add_argument('-t', '--target-directory', type=str, default='.',
help="An output directory to store output files.")
parent.add_argument('-i', '--in-place', action='store_true',
help="After succesful execution, delete the inputs.")
# The inputfiles should be the very last positional argument.
parent.add_argument('inputfiles', nargs='*', type=argparse.FileType('r'),
help="A list of input files to operate on.")

# Top level parser.
top_description = "This is mytool. It does stuff"
parser = argparse.ArgumentParser(prog="mytool",
description=top_description,
parents=[parent])

# Operation parsers.
subparsers = parser.add_subparsers(help='Sub-command help', dest='chosen_op')

op_parsers = {}
for op_name, op in IMPLEMENTED_OPERATIONS.items():
op_parsers[op_name] = subparsers.add_parser(op_name,
description=op.description,
parents=[parent])
if op.argument is not None:
op_parsers[op_name].add_argument(op.argument)

args = parser.parse_args()
op_args = {}
for key, subparser in op_parsers.items():
op_args[key] = subparser.parse_args()


print(args.chosen_op)

我遇到的问题是位置参数的顺序错误。不知何故,我实现这一点的方式使 Argparse 认为该操作(及其 op_argument)应该出现在输入文件之后,但显然情况并非如此。

如何将父位置参数(在我的例子中为输入文件)作为最后一个位置参数?

最佳答案

对于主解析器来说,subparsers 只是另一个位置参数,但具有唯一的 nargs('+...')。因此,它将首先查找inputfiles 参数,然后将剩余的内容分配给subparsers

将位置与子解析器混合是很棘手的。最好将 inputfiles 定义为每个子解析器的参数。

parents 可以轻松地将同一组参数添加到多个子解析器 - 但这些参数将首先添加。

所以我认为你想要:

for op_name, op in IMPLEMENTED_OPERATIONS.items():
op_parsers[op_name] = subparsers.add_parser(op_name,
description=op.description,
parents=[parent])
if op.argument is not None:
op_parsers[op_name].add_argument(op.argument)

op_parsers[op_name].add_argument('inputfiles', nargs='*', type=argparse.FileType('r'),
help="A list of input files to operate on.")

至于帮助,正常行为是获取主解析器或每个子解析器的帮助。将这些组合成一个显示器一直是几个 SO 问题的主题。这是可能的,但并不容易。

<小时/>

主解析器按顺序处理输入字符串 - 标志、位置等。当它处理子解析器位置时,它将任务以及所有剩余的命令行字符串交给名称子解析器。然后,子解析器就像一个新的独立解析器一样,并将命名空间返回到主解析器以合并到主命名空间中。主解析器不会继续解析命令行。因此子解析器操作始终是最后一个。

关于python - Argparse:将父解析器与子解析器混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44809222/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com