将argparse别名解析回原始命令 - python

我正在使用subparser/subcommand that has an alias。

我在子解析器中使用dest选项来存储子命令的名称,以便以后使用。

当前,如果子命令的名称为reallyLongName,别名为r(例如),则dest选项将完全存储reallyLongNamer-我输入的内容都会被存储。这很烦人,因为我现在必须检查命令的名称或其别名以识别命令。

有没有办法让argparse将子命令的名称存储在某种形式的单个规范文本字符串中的dest字段中?

例如,给出以下代码:

import argparse

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers(dest='command', help='sub-command help')

parser_ag = subparsers.add_parser(  'mySubcommand',
                                    aliases=['m'],
                                    help='Subcommand help')

print(parser.parse_args('mySubcommand'.split()))

print(parser.parse_args('m'.split()))

产生以下输出:

Namespace(command='mySubcommand')
Namespace(command='m')

所需的结果:command两者都有一个单一的规范值,例如:

Namespace(command='mySubcommand')
Namespace(command='mySubcommand')

参考方案

令人惊讶的是,这很难被发现。添加子解析器时,它会存储在父级._actions属性中。从那里开始,只需挖掘属性即可获得所需的内容。下面,我创建字典以按dest名称引用子解析器参数,然后添加了一个函数,该函数使我们可以将输入的参数重新映射到主要参数名称。

from collections import defaultdict

def get_subparser_aliases(parser, dest):
    out = defaultdict(list)
    prog_str = parser.prog
    dest_dict = {a.dest: a for a in parser._actions}
    try:
        choices = dest_dict.get(dest).choices
    except AttributeError:
        raise AttributeError(f'The parser "{parser}" has no subparser with a `dest` of "{dest}"')

    for k, v in choices.items():
        clean_v = v.prog.replace(prog_str, '', 1).strip()
        out[clean_v].append(k)
    return dict(out)

def remap_args(args, mapping, dest):
    setattr(args, dest, mapping.get(getattr(args, dest)))
    return args

使用您的示例,我们可以使用以下方法重新映射解析参数:

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='command', help='sub-command help')
parser_ag = subparsers.add_parser('mySubcommand',
                                  aliases=['m'],
                                  help='Subcommand help')

args = parser.parse_args('m'.split())
mapping = get_subparser_aliases(parser, 'command')
remap_args(args, mapping, 'command')
print(args)
# prints:
Namespace(command='mySubcommand')

这是在多个子解析器级别上使用的示例。.我们有一个带有可选参数和一个子解析器的解析器。子解析器具有3个可能的参数,最后一个调用具有2个可能参数的另一个子解析器(子子解析器)。

您可以检查顶级解析器或一级子解析器以查看别名映射。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--someoption', '-s', action='store_true')

subparser1 = parser.add_subparsers(help='sub-command help', dest='sub1')
parser_r = subparser1.add_parser('reallyLongName', aliases=['r'])
parser_r.add_argument('foo', type=int, help='foo help')
parser_s = subparser1.add_parser('otherReallyLong', aliases=['L'])
parser_s.add_argument('bar', choices='abc', help='bar help')
parser_z = subparser1.add_parser('otherOptions', aliases=['oo'])

subparser2 = parser_z.add_subparsers(help='sub-sub-command help', dest='sub2')
parser_x = subparser2.add_parser('xxx', aliases=['x'])
parser_x.add_argument('fizz', type=float, help='fizz help')
parser_y = subparser2.add_parser('yyy', aliases=['y'])
parser_y.add_argument('blip', help='blip help')

get_subparser_aliases(parser, 'sub1')
# returns:
{'reallyLongName': ['reallyLongName', 'r'],
 'otherReallyLong': ['otherReallyLong', 'L'],
 'otherOptions': ['otherOptions', 'oo']}

get_subparser_aliases(parser_z, 'sub2')
# returns:
{'xxx': ['xxx', 'x'], 'yyy': ['yyy', 'y']}

通过上面的函数使用它,我们可以将收集到的参数重新映射为它们的较长名称。

args = parser.parse_args('-s oo x 1.23'.split())
print(args)
# prints:
Namespace(fizz=1.23, someoption=True, sub1='oo', sub2='x')

for p, dest in zip((parser, parser_z), ('sub1', 'sub2')):
    mapping = get_subparser_aliases(p, dest)
    remap_args(args, mapping, dest)

print(args)
# prints:
Namespace(fizz=1.23, someoption=True, sub1='otherOptions', sub2='xxx')

R'relaimpo'软件包的Python端口 - python

我需要计算Lindeman-Merenda-Gold(LMG)分数,以进行回归分析。我发现R语言的relaimpo包下有该文件。不幸的是,我对R没有任何经验。我检查了互联网,但找不到。这个程序包有python端口吗?如果不存在,是否可以通过python使用该包? python参考方案 最近,我遇到了pingouin库。

Python:传递记录器是个好主意吗? - python

我的Web服务器的API日志如下:started started succeeded failed 那是同时收到的两个请求。很难说哪一个成功或失败。为了彼此分离请求,我为每个请求创建了一个随机数,并将其用作记录器的名称logger = logging.getLogger(random_number) 日志变成[111] started [222] start…

Python-Excel导出 - python

我有以下代码:import pandas as pd import requests from bs4 import BeautifulSoup res = requests.get("https://www.bankier.pl/gielda/notowania/akcje") soup = BeautifulSoup(res.cont…

Matplotlib'粗体'字体 - python

跟随this example:import numpy as np import matplotlib.pyplot as plt fig = plt.figure() for i, label in enumerate(('A', 'B', 'C', 'D')): ax = f…

Python:如何根据另一列元素明智地查找一列中的空单元格计数? - python

df = pd.DataFrame({'user': ['Bob', 'Jane', 'Alice','Jane', 'Alice','Bob', 'Alice'], 'income…