How can I parse these arguments most efficiently in python?

So I am trying to come up with a strategy using the argparse library.

This is how I want to interact with my program:

$ program list [<number>] 
$ program check <name>
$ program watch <name> [<quality>]

      

I now have an argument parser as shown below:

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('list')
group.add_argument('check')
group.add_argument('watch')

      

But how can I add an optional argument like an integer to an existing argument?

A user value can invoke a list command in the following ways:

program list 

      

If the list action will be called with a default value or:

program list 10

      

If list action will be called with argument 10.

I saw the subcommand parameter in the documentation, but I ran into a problem where I would have a helper parser for the list arguments, but then I would have to add a flag like -n and then provide the number. Perhaps this is the best way to do it? But I like the idea of ​​just specifying the number if you want, or omitting it if you don't.

Am I trying to achieve good practice? Is this possible with argparse?

+3


source to share


1 answer


This pattern put me in the wrong direction. At the end, I sketched out the implementation of subparser, which I think does the trick.

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('list')
group.add_argument('check')
group.add_argument('watch')

      

It expects 3 lines and will assign them to 3 attributes.

However, you cannot put 3 'positional' arguments in a mutually exclusive group. One optional positional (yes, the terminology is confused) can be in such a group, but the rest should be "optionals" (flagged).


Return to the original list. Are these different patterns that you would like to adopt

program list [integer]
program check name
program watch name [quality]

      

where 'list', 'check', 'watch' are literal strings and 'integer', 'name', 'quality' are variable names.



If this is the case, then subpers are probably the best choice. nargs='?'

can be used to make positional arguments "optional".

parser = argparse.ArgumentParser()
sp = parser.add_subparsers(dest='cmd')  # put the command string in `cmd` attribute
p1 = sp.add_parser('list')
p2 = sp.add_parser('check')
p3 = sp.add_parser('watch')
p1.add_argument('value',dtype=int, nargs='?') # ok with 0 or 1 values
p2.add_argument('name')
p3.add_argument('name')
p3.add_argument('quality',nargs='?')

      

value

and quality

will get the default value if none of them are explicitly specified. The default default

is None

. But you can define a meaningful alternative, eg. default=0

for an integer value.


You can also define a parser, for example:

parser = ...
parser.add_argument('command', choices=['list','check','watch'])
parser.add_argument('rest', nargs='*')

      

This will wait for one of three command commands and put anything else in the "rest" attribute (like a list of strings). Then you can interpret these lines however you want.

+2


source







All Articles