My Program should include the following options, properly parsed by argparse:
[-h, --help]
and [-v, --version]
[-f FILE, --file FILE]
and [-u URL, --url URL]
--url
was chosen: [-V, --verbose]
--file
or --url
was chosen: [-F, --format FORMAT]
The desired usage pattern would be:
prog.py [-h] [-v] [-f FILE (-F FORMAT) | -u URL [-V] (-F FORMAT) ]
with the -F
requirement applying to both members of the mutually exclusive group.
Not sure if it rather be a positional.
So it should be possible to run:
prog.py -u "http://foo.bar" -V -F csv
and the parser screaming in case i forgot the -F
(as he's supposed to).
What i've done so far:
parser = ArgumentParser(decription='foo')
group = parser.add_mutually_exclusive_group()
group.add_argument('-f','--file', nargs=1, type=str, help='')
group.add_argument('-u','--url', nargs=1, type=str, help='')
parser.add_argument('-V','--verbose', action='store_true', default=False, help='')
parser.add_argument('-F','--format', nargs=1, type=str, help='')
Since it has a 'vanilla mode' to run without command line arguments, all arguments must be optional.
How can i implement points 3. and 4. into my code?
EDIT:
I tried -f
and -u
as subparsers, as described here, but subcommands seem to be treated like positionals and the parser gives me an error: too few arguments
if i run it without arguments.
Use of nargs=2 and tuple metavar approximates your goal
parser = argparse.ArgumentParser(prog='PROG')
group = parser.add_mutually_exclusive_group()
group.add_argument('-f','--file', nargs=2, metavar=('FILE','FORMAT'))
group.add_argument('-u','--url', nargs=2, metavar=('URL','FORMAT'))
parser.add_argument('-V','--verbose', action='store_true',help='optional with url')
which produces:
usage: PROG [-h] [-f FILE FORMAT | -u URL FORMAT] [-V]
optional arguments:
-h, --help show this help message and exit
-f FILE FORMAT, --file FILE FORMAT
-u URL FORMAT, --url URL FORMAT
-V, --verbose optional with url
This requires the format along with filename or url, it just doesn't require the -F
. As others noted -V
can be ignored in the -f
case.
I tried -f and -u as subparsers, as described here, but subcommands seem to be treated like positionals and the parser gives me an error: too few arguments if i run it without arguments.
In the latest version(s) subcommands are no longer treated as required positionals. This was, as best I can tell, a side effect of changing the error message to be more informative. Instead of _parse_known_args
doing a:
if positionals:
self.error(_('too few arguments'))
it scans _actions
to see which are required, and then lists them by name in the error message. This is discussed in http://bugs.python.org/issue9253 . I know this change is in development (3.4), and may also be in 3.3.
These points can enforced in optparse
using a callback method when a certain option is present.
However, in argparse
these are not available.
You can add a subparser for the url
and the file
sub-option, and parse these seperatly.
from the help:
Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present.
But I would just properly document the usage, and just ignore the arguments that are not applicable.
e.g. let these two command lines behave exactly the same:
prog.py -f FILE -V
prog.py -f FILE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With