как дать парсеру распечатать справочное сообщение вместо ошибки и выйти - PullRequest
5 голосов
/ 30 декабря 2010

Я использую argparse для обработки аргументов cmd, я хочу, если аргументы не указаны, затем вывести сообщение справки, но теперь анализ выдаст ошибку и завершится.мой код:

def main():
    print "in abing/start/main"
    parser = argparse.ArgumentParser(prog="abing")#, usage="%(prog)s <command> [args] [--help]")
    parser.add_argument("-v", "--verbose", action="store_true", default=False, help="show verbose output")

    subparsers = parser.add_subparsers(title="commands")

    bkr_subparser = subparsers.add_parser("beaker", help="beaker inspection")
    bkr_subparser.set_defaults(command=beaker_command)
    bkr_subparser.add_argument("-m", "--max", action="store", default=3, type=int, help="max resubmit count")
    bkr_subparser.add_argument("-g", "--grain", action="store", default="J", choices=["J", "RS", "R", "T", "job", "recipeset", "recipe", "task"], type=str, help="resubmit selection granularity")
    bkr_subparser.add_argument("job_ids", nargs=1, action="store", help="list of job id to be monitored")

    et_subparser = subparsers.add_parser("errata", help="errata inspection")
    et_subparser.set_defaults(command=errata_command)
    et_subparser.add_argument("-w", "--workflows", action="store_true", help="generate workflows for the erratum")
    et_subparser.add_argument("-r", "--run", action="store_true", help="generate workflows, and run for the erratum")
    et_subparser.add_argument("-s", "--start-monitor", action="store_true", help="start monitor the errata system")
    et_subparser.add_argument("-d", "--daemon", action="store_true", help="run monitor into daemon mode")
    et_subparser.add_argument("erratum", action="store", nargs=1, metavar="ERRATUM", help="erratum id")

    if len(sys.argv) == 1:
        parser.print_help()
        return

    args = parser.parse_args()
    args.command(args)

    return

как я могу это сделать?спасибо.

1 Ответ

3 голосов
/ 30 декабря 2010

Решение состоит в создании подкласса argparse.ArgumentParser и переопределении его error() метода. На самом деле, при ошибке ArgumentParser вызывает метод error(). Затем пользовательский анализ аргументов может быть выполнен через подкласс вместо argparse.ArgumentParser. Модель источника error() найдена в источнике для argparse:

def error(self, message):
    """error(message: string)

    Prints a usage message incorporating the message to stderr and
    exits.

    If you override this in a subclass, it should not return -- it
    should either exit or raise an exception.
    """
    self.print_usage(sys.stderr)
    self.exit(2, '%s: error: %s\n' % (self.prog, message))

Например, можно вызвать исключение в error() вместо печати сообщения, так что код, вызывающий parse_args(), решает проблемы с пользовательскими параметрами.

Оригинальный ответ : согласно пояснениям в комментариях, следующее не работает. Однако он предоставляет механизм доступа к справочным сообщениям из функций подкоманд:

Это почти у вас есть: в каждой из *_command(args) функций вы можете проверить размер args и вывести сообщение об ошибке, если аргументов недостаточно.

Если вы хотите использовать автоматически сгенерированную справку, в ваших командных функциях вы можете получить ее, передав подпарасеры каждой команде, например:

args.command(subparsers, args)  # Instead of args.command(args)

Каждая функция *_command() должна просто принимать два аргумента вместо одного. Сгенерированная автоматически справка доступна через:

subparsers.choices['beaker'].print_help()  # or print_usage()

например.

В качестве альтернативы вы можете выбрать прямую передачу конкретного подпарамера в каждую подпрограмму подкоманды *_command():

args.command(subparsers.choices[sys.argv[1]], args)

, а затем в каждом *_command(subparser, args) распечатайте справку с subparser.print_help().

...