替换argparse中的参数

时间:2017-09-19 22:43:03

标签: python argparse

我有一个我无法修改的基类(代码可能有其他错误,但请忽略它们)

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"))

2 个答案:

答案 0 :(得分:3)

如果您无法修改基类实现,则可以进入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),但是否则使用公共接口。

答案 1 :(得分:1)

add_argument创建一个Action对象,该对象对add_argument调用中给出的参数进行编码。创建后可以读取和/或修改它们。

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")

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

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

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