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

2024-02-29

我想写一个简单的工具任意数量的输入文件并执行one对他们每个人进行操作。语法非常简单:

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 问题的主题。这是可能的,但并不容易。


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Argparse:将父解析器与子解析器混合 的相关文章

  • Python - 套接字错误,地址正在使用

    我目前正在尝试在 Xubuntu 12 10 x64 上设置 SiriServer 这不是重点 当我运行服务器时 python 返回错误 socket error Errno 98 Address already in use 默认情况下
  • 如何使用 Python 的 __import__ 函数执行相当于“从模块导入 *”的操作?

    给定一个带有模块名称的字符串 如何导入模块中的所有内容 就好像您调用了 from module import 即给定字符串 S module 如何获得与以下内容等效的内容 import S fromlist 这似乎没有按预期执行 因为它没有
  • ImportError:尝试在没有已知父包的情况下进行相对导入[重复]

    这个问题在这里已经有答案了 我正在学习使用 python 编程 并且在从包中的模块导入时遇到问题 我正在使用 Visual Studio 代码和 Python 3 8 2 64 位 我的项目目录 https i stack imgur co
  • pip 中的新彩色终端进度条

    我发现新版本的pip Python的包安装程序 有一个彩色进度条来显示下载进度 我怎样才能做到这一点 Like this pip 本身正在使用rich https pypi org project rich 包裹 特别是 他们的进度条文档
  • 如何将值从 recyclerview 项目传递到另一个活动

    当我们单击 recyclerview 项目时 我试图将 recyclerview 项目中的值传递给另一个活动 这里我使用的是OnItemTouchListener 我从 JSON 检索数据并将其解析为 ArrayList 我保存了5个参数
  • 如何将 pymongo.cursor.Cursor 转换为字典?

    我正在使用 pymongo 查询一个区域内的所有项目 实际上是查询地图上一个区域内的所有场馆 我用了db command SON 在搜索球形区域之前 它可以返回一本字典 字典中有一个名为results其中包含场馆 现在我需要在一个正方形区域
  • 在 Python 中打开文本文件时出现问题

    这看起来应该很简单 f open C Users john Desktop text txt r 但我收到此错误 Traceback most recent call last File
  • 用户在对话框中输入

    python 中是否有任何库可用于图形用户输入 我知道关于tk但我相信需要一些代码才能做到这一点 我正在寻找最短的解决方案 a input Enter your string here 取而代之的是 我想要一个对话框 以便用户可以在那里输入
  • 如何从 __subclasses__ 中删除类?

    当从类继承时 子类可以通过父类访问 subclasses method class BaseClass pass class SubClass BaseClass pass BaseClass subclasses
  • AMD plaidml 与 CPU Tensorflow - 意外结果

    我目前正在运行一个简单的脚本来训练mnist数据集 通过 Tensorflow 通过我的 CPU 运行训练给了我49us sample和使用以下代码的 3e 纪元 CPU import tensorflow as tf mnist tf k
  • Python elasticsearch DSL 聚合/每个文档嵌套值的度量

    我试图找到 2 级嵌套中的最小值 每个文档单独的最小值 到目前为止 我能够进行聚合 计算搜索结果中所有嵌套值的最小值 但无需按文档进行分隔 我的示例架构 class MyExample DocType myexample id Intege
  • Numpy - 两个矩阵的行之间的协方差

    我需要计算两个不同矩阵的每一行之间的协方差 即第一个矩阵的第一行与第二个矩阵的第一行之间的协方差 依此类推 直到两个矩阵的最后一行 我可以在没有 NumPy 的情况下使用下面附加的代码来完成此操作 我的问题是 是否可以避免使用 for 循环
  • 如何提取数字(以及比较形容词或范围)

    我正在用 Python 开发两个 NLP 项目 它们都有类似的任务提取数值和比较运算符来自句子 如下所示 greater than 10 weight not more than 200lbs height in 5 7 feets fas
  • 利用“写入时复制”将数据复制到 Multiprocessing.Pool() 工作进程

    我有一点multiprocessingPython 代码看起来有点像这样 import time from multiprocessing import Pool import numpy as np class MyClass objec
  • 如何将目录导入为 python 模块

    如果有目录 home project aaa 我知道它是一个Python包 那么 我如何通过知道它的路径来导入这个模块 这意味着 我希望代码能够正常工作 aaa load module home project aaa 我知道的唯一方法是
  • App Engine、PIL 和叠加文本

    我正在尝试在 GAE 上的图像上覆盖一些文本 现在他们公开了 PIL 库 这应该不是问题 这就是我所拥有的 它有效 但我不禁认为我应该直接写入背景图像 而不是创建单独的覆盖图像然后合并 我可以用吗Image frombuffer http
  • 使用 NaN 获取 pandas 系列模式的最快方法

    我需要找到 pandas groupby 对象或单个系列的模式 最常见元素 为此我有以下函数 def get most common srs from collections import Counter import numpy as n
  • 为什么这个多处理代码会失败? [复制]

    这个问题在这里已经有答案了 def sample pass Process target sample start Process target sample start 上面的代码失败并出现错误 已尝试在当前进程之前启动新进程 进程已完成
  • Python TDD 目录结构

    Python 中是否有用于 TDD 的特定目录结构 教程讨论测试的内容 但不讨论测试的位置 通过研究 Python Koans 怀疑它是这样的 project main program py This has main method sta
  • 用 Ruby 或 Python 解析 SVG 的库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 SVG 是一个庞大的标准 它基于 XML 我过去曾将 SVG 解析为 XML 然而 有些事情很难 例如

随机推荐