替换 argparse 中的参数

Replacing argument in argparse

我有一个基础class我不能修改(代码可能有其他错误,但请忽略那些)

class BaseClass(object):
    def __init__(self):
        self.parser = argparse.ArgumentParser()
        self.parser.add_argument("arg1", choices=("a", "b"))

我想要的是如下覆盖arg1

class DerivedClass(BaseClass):
    def __init__(self):
        BaseClass.__init__(self)
        self.parser.add_argument("arg1", choices=("a", "c", "d"))

add_argument 创建一个 Action 对象,该对象对 add_argument 调用中给出的参数进行编码。那些可以阅读and/or创建后修改

class BaseClass(object)
    def __init__(self):
        self.parser = argparse.ArgumentParser()
        self.arg = self.parser.add_argument("arg1", choices=("a", "b"))
        # self.arg is now the Action object defined by this add_argument method

class DerivedClass(BaseClass):
    def __init__(self):
        BaseClass.__init__(self)
        # modify the choices attribute of self.arg
        self.arg.choices = ("a","b","c")

该 Action 对象也可以在 parser._actions 列表中找到,但我更愿意在我自己的代码中保存一个引用。

(此代码尚未经过测试,因此可能会出现一两个错误。)


class BaseClass(object):
    def __init__(self):
        self.parser = argparse.ArgumentParser(prog="BASE")
        self.parser.add_argument("arg1", choices=("a", "b"))
        self.parser.add_argument('-f','--foo')

class DerivedClass(BaseClass):
    def __init__(self):
        BaseClass.__init__(self)
        self.parser.prog = "DERIVED"
        print(self.parser._actions)

在创建 DerivedClass 时显示此列表:

[_HelpAction(option_strings=['-h', '--help'], dest='help', nargs=0, const=None, default='==SUPPRESS==', type=None, choices=None, help='show this help message and exit', metavar=None), 
 _StoreAction(option_strings=[], dest='arg1', nargs=None, const=None, default=None, type=None, choices=('a', 'b'), help=None, metavar=None), 
 _StoreAction(option_strings=['-f', '--foo'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)]

所以添加:

    idx = [a.dest for a in self.parser._actions].index('arg1')
    self.parser._actions[idx].choices = ("a","b","c")

p1 = BaseClass()
p1.parser.print_help()

p2 = DerivedClass()
p2.parser.print_help()

产生 2 种用法:

usage: BASE [-h] [-f FOO] {a,b}

positional arguments:
  {a,b}

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

usage: DERIVED [-h] [-f FOO] {a,b,c}

positional arguments:
  {a,b,c}

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

如果您不能修改基础 class 实现,您 可以 进入 parser 的属性并修改您关心的特定操作关于。下面是演示这一点的代码草图:

from base import BaseClass


def _modify_choices(parser, dest, choices):
    for action in parser._actions:
        if action.dest == dest:
            action.choices = choices
            return
    else:
        raise AssertionError('argument {} not found'.format(dest))


class MySubClass(BaseClass):
    def __init__(self):
        super(MySubClass, self).__init__()
        _modify_choices(self.parser, 'arg1', ('a', 'b', 'c'))


def main():
    inst = MySubClass()
    inst.parser.parse_args()


if __name__ == '__main__':
    exit(main())

和用法:

$ python subclass.py d
usage: subclass.py [-h] {a,b,c}
subclass.py: error: argument arg1: invalid choice: 'd' (choose from 'a', 'b', 'c')

请注意,这涉及私有实现细节(特别是 ArgumentParser._actions),但在其他方面使用 public 接口。