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?
source to share
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.
source to share