Pergunta

I am using argparse to handle cmd args, I wanna if there is no args specified, then print the help message, but now the parse will output a error, and then exit. my code is:

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

how can I do that? thanks.

Foi útil?

Solução

A solution consists in subclassing argparse.ArgumentParser and redefining its error() method. In fact, upon error, ArgumentParser calls its error() method. The custom argument parsing can then be performed through the subclass instead of argparse.ArgumentParser. A model error() function is found in the source for 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))

It is for instance possible to raise an exception in error(), instead of printing a message, so that the code calling parse_args() takes charge of problems with the user parameters.

Original answer: according to the clarification in the comments, the following does not work. However, it provides a mechanism for accessing help messages from the sub-command functions:

You almost have it: in each of your *_command(args) functions, you can test the size of args and print an error message if there are not enough arguments.

If you want to use the automatically generated help, in your command functions, you can get it by passing the subparsers to each command, like so:

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

Each *_command() function should then simply take two arguments instead of one. The automatically generated help is accessible through:

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

for instance.

You could alternatively choose to directly pass the particular subparser to each sub-command routine *_command():

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

and then, in each *_command(subparser, args), print the help with subparser.print_help().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top