【问题标题】:Python using diferent options multiple times with argparsePython 通过 argparse 多次使用不同的选项
【发布时间】:2020-10-12 22:04:41
【问题描述】:

我正在编写一个自定义 Nagios 脚本,我想在其中以与现有 Nagios 插件 check_disk 上使用的相同方式实现命令行参数的解析。

在该插件中,您有一个选项参数 -CClear 当前配置并使用新参数重新开始。

摘自check_disk帮助:

check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar
           ----(3)-----    ---------(1)----------    --------(2)--------

检查警告/严重阈值:

  1. 对于卷 /foo,使用 1000M 和 500M 作为阈值
  2. 对于音量 /bar 使用 5% 和 3%
  3. 所有剩余卷使用 100M 和 50M

我已经尝试使用argparse 和一些参数作为action='append',但重复的参数存储在一个列表中,缺少的参数不包含在“无”条目中。

我也尝试过 parse_known_args 希望停止解析第一个 unknown 参数,但我得到了一个包含所有已知参数和未知参数列表的命名空间。

我想我唯一的选择是在解析命令行参数之前使用正则表达式。

import re
import argparse
import sys

parser = argparse.ArgumentParser()
parser.add_argument('-w', help='warning')
parser.add_argument('-c', help='critical')
parser.add_argument('-p', help='path')

separator=r'-S'
groups = re.split(separator, '|'.join(sys.argv[1:])))

args = []
for idx, group_args in enumerate(groups):
   args.append('')
   args[idx]=parser.parse_args(group_args.split('|'))

不知道argparse是否可以不用正则表达式分割处理这种场景。

或者,如果这是我能找到的最佳方法。

这与Using the same option multiple times in Python's argparse 无关,因为它不是同一种情况,我有不同的可选参数,而不仅仅是一个具有多个值的选项。

在上面的例子中(3)没有选项-p,(1)和(2)有它。这是差异之一,也是问题之一。如果所有选项都是强制性的,那就很容易了。

【问题讨论】:

  • 你想要的不适合 argparse 解析方法,如果有的话。它按照用户提供的顺序独立处理标记选项(append 处理的除外)。您可以使用nargs(例如 3 或 +)来近似您想要的结果。
  • 在设计花哨的 API 时请记住,您必须向用户解释它。 argparse 很简单,usage 可以自动生成(甚至代码很脆弱)。
  • 不幸的是,argparse 不会直接执行您想要的操作,因此您将输入参数预解析为组的想法可能是唯一的选择。我也不知道任何其他可以处理此用例的参数解析工具(我认为我已经查看了所有这些工具)。
  • @FMc 你能发表你的评论作为答案吗?

标签: python regex argparse


【解决方案1】:

处理这个问题:

check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar

我可以想象从命名空间开始

args = argparse.Namespace(w:[None], c:[None], p:[None])
args = parser.parse_args(args=args)

并定义几个自定义 Action 类。

For `-C` use a class that appends a `None` to each of those 3 attributes
    namespace['w'].append(None), etc

For each of `w`, `c` and `p`, an Action class, that replaces the last `None`
    with the users value.  

换句话说,使用C 参数通过推进列表来“重置”,然后使用其他参数来调整默认默认值。

或者以Namespace(C=[[None, None, None]]) 开头,然后添加一个带有每个“C”的附加列表。然后 'w' 将设置 namespace['C'][-1][0] 等(或使用字典列表)。

【讨论】:

  • 你能用一些工作代码澄清你的答案吗?我刚刚尝试了你的前两行并得到了一个错误。我有一个工作代码,但使用正则表达式和预处理参数。我喜欢你的方法,但我想知道你的想法是否可以写下来或者只是一个想法。
猜你喜欢
  • 1970-01-01
  • 2017-05-24
  • 2021-06-05
  • 2013-07-06
  • 2016-08-11
  • 2013-06-24
  • 2018-10-05
  • 2013-11-11
  • 2017-03-12
相关资源
最近更新 更多