Pergunta

I'm using Argparser to handle arguments for my CLI prog. But as the time passed I think that It's not a good Idea to use it. Here comes the problem. I want to use options without any prefix character. Like git commit or svn move. I've searched a little and found that Argparse has a add_subparser() method. Let us populate our foo prog:

parser = argparse.ArgumentParser(prog='foo', usage='%(prog)s [options]')

subparsers = parser.add_subparsers(help='sub-command help')
parser_a = subparsers.add_parser('add', help='a help')
parser_a.add_argument('-ap', '--add-project',
                    nargs='*',
                    action='store',
                    help="Add project")

parser_d = subparsers.add_parser('del', help='a help')
parser_d.add_argument('-dp', '--delete-project',
                    nargs='*',
                    action='store',
                    help="Delete project")

args = parser.parser_args()

Now let execute foo with options and print args namespace(I didn't the past the whole code, you get the point):

$ ./foo del
Namespace(delete_project=None)
$ ./foo add
Namespace(add_project=None)

As you see, if I execute the option del, add_project is not passed to the variable args. That causes problems if I have an "if clause" in my main() function like

def main(args):

   if args.delete_project:
      ...
   if args.add_project:
      ...

I'll get an AttributeError exception, that the Namespace has no attribute with the name add_project if I execute ./foo del. Besides that, I'm not able to pass any argument to the options del and add. I've also set prefix_chars to an empty string, that didn't work either.

What is way to handle it ? Is argparse capable to create options like git,svn, etc.. or should I create my own function and handle all arguments myself ?

Foi útil?

Solução

Instead of your if statements, the argparse docs recommend something like this:

parser_X.set_defaults(action=action_func)
args.action(args)

Then the add_action will look at add_project, and del_action at del_project.

Outras dicas

Edit: Apparently the default for default is None, which means we don't have one, so you'll have to use True and False (which is the right way anyhow).

You need to add the default when you add your argument to the parser:

parser_a.add_argument('-ap', '--add-project',
                    nargs = '*',
                    action = 'store_true',
                    default = False,
                    help = "Add project")

You can see the documentation for the add_argument method here. (I realize the argparse doc layout isn't the most conducive to figuring out how to do things that aren't called out in the examples)

Also, as Tobu appropriately points out in his answer, the unused subparsers don't get invoked, so you can't safely probe their values without at least protecting your code in a try: block. However, really you should use the functionality of associating an action with your subparsers unless you have a much more complex situation where they need to share state.

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