Я бы пошел с опцией подкоманд .
Вам не обязательно нужно больше кодировать: создавать классы команд, каждый из которых имеет свою собственную настройку (используя наследование, где это необходимо), в вашем Main
классе Cli создать экземпляр основного синтаксического анализатора, а затем передать его командам, которые будут заботиться добавить / установить собственный подпарсер .
Ответ короткий, но если неясно, скажите мне, и я добавлю пример кода.
Грубый пример
Вы должны строить свои команды как классы:
class Install(BaseCommand):
help = "download and install packages"
@classmethod
def interface(cls, cmd_parser):
cmd_parser.add_argument('--foo')
cmd_parser.set_defaults(cmd=cls) # this line is very important
def start(self, foo=None):
# command execution
И ваш интерфейс командной строки тоже должен быть классом:
class Main(BaseCli):
def __init__(self):
self.commands = [Install] # just the command classes
self._parser = argparse.ArgumentParser()
self._subparsers = self._parser.add_subparsers()
def load_interface(self):
for cmd in self.commands:
cmd_parser = self.add_command_parser(help=cmd.help)
cmd.interface(cmd_parser)
def add_command_parser(self, *args, **kwargs):
return self._subparsers.add_parser(*args, **kwargs)
def parse_args(self, args=None, namespace=None):
return self._parser.parse_args(args, namespace)
def start_session(self, namespace):
# this will instantiate the appropriate command class
cmd = namespace.cmd()
# and call its start method with the user args
cmd.start(**namespace.__dict__)
Для использования следующим образом:
cli = Main()
cli.load_interface()
args = cli.parse_args()
cli.start_session(args)
Обратите внимание, что при таком подходе у вас будет вся сила наследования на вашей стороне! :)