Когато се използва argparse, той осигурява автоматична обработка за -h/--help команди. Дори и да са добавени подразбори, той обработва тяхната „помощ за подразбори“, както и глобална помощ, която предоставя списък на тези подразбори.

Дотук добре.

Добавяне на помощна команда

Учтивост към потребителя е да добавите helpcommand, ако се използват подпарсери. Най-добрата практика е да дадете на потребителя и двата начина да види помощ: program subcommand --help и program help subcommand.

За съжаление, argparse не предоставя такъв лукс. Човек трябва да го направи сам.

Дисекция на проблем

  1. Добавете команда help. Тривиално, просто добавете още един подпарсер.
  2. Намерете даден поданализатор от друг поданализатор и намерете всички поданализатори
  3. Намерете как да отпечатате помощ за даден подпарсер

Налични данни и обхват: Извикваме command на поданализатора (най-добрата практика е да използваме subparser.set_defaults(command=myfunc); имаме достъп само до поданализатора, но не и до самия ArgumentParser(). Такова нещо се случва често, когато разделяте команди на автономни класове със следния код:

subparsers = self.parser.add_subparsers(title=’commands’)
FirstCommand(subparsers)
SecondCommand(subparsers)

и всяка команда добавя собствени опции като тази:

class GenericCommand(object):
    def __init__(self, subparsers):
        self.parser = subparsers.add_parser(self.name, help=self.help)
           self.parser.add_argument(...)
           ...
           subparsers.set_defaults(command=self.command)
    def command(self, args):
        ....

Търсене на подпарсери

Доста разочароващо е, но и dict(subparsers), и list(subparsers) не работят. Документацията не изяснява вътрешността на argparse, така че използвах интроспекция, за да погледна вътре.

Открих, че subparsers има атрибут .choices, който съдържа всички налични подпарсери като OrderedDict. Може да бъде достъпен чрез ключ, може да се повтори над ключове или стойности. Всичко, от което се нуждаем.

Помощно съобщение

Всеки подпарсер или съдържание на choices има функция print_help(), която прави всичко, както очаквате.

Полученият код

class HelpCommand(object):
    def __init__(self, subparsers):
        self.parser = subparsers.add_parser(
            'help',
             help='display help'
        )
        self.parser.add_argument(
            'name',
             nargs='?',
             help='Command to show help for'
        )
        self.subparsers = subparser
        self.parser.set_defaults(command=self.command)
    def command(self, args):
        if args.name:
            self.subparsers.choices[args.name].print_help()
        else:
            print("Use help [name] to show help for given command")
            print("List of available commands:")
            print("\n".join(list(self.subparsers.choices.iterkeys())))
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(title='commands')
FirstCommand(subparsers)
SecondCommand(subparsers)
HelpCommand(subparsers)
args = parser.parse_args()
args.command()