Python2.7 argparse only accepts optional arguments (prefixed) in mutually exclusive groups:
parser = argparse.ArgumentParser(prog='mydaemon') action = parser.add_mutually_exclusive_group(required=True) action.add_argument('--start', action='store_true', help='Starts %(prog)s daemon') action.add_argument('--stop', action='store_true', help='Stops %(prog)s daemon') action.add_argument('--restart', action='store_true', help='Restarts %(prog)s daemon')
$ mydaemon -h
usage: mydaemon [-h] (--start | --stop | --restart) optional arguments: -h, --help show this help message and exit --start Starts mydaemon daemon --stop Stops mydaemon daemon --restart Restarts mydaemon daemon
Is there a way to make argparse arguments behaves like traditional unix daemon control:
(start | stop | restart) and not (--start | --stop | --restart) ?
To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.
In logic, two mutually exclusive propositions are propositions that logically cannot be true in the same sense at the same time. To say that more than two propositions are mutually exclusive, depending on the context, means that one cannot be true if the other one is true, or at least one of them cannot be true.
Number of Arguments If you want your parameters to accept a list of items you can specify nargs=n for how many arguments to accept. Note, if you set nargs=1 , it will return as a list not a single value.
from pymotw
import argparse parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument('-a', action='store_true') group.add_argument('-b', action='store_true') print parser.parse_args()
output:
$ python argparse_mutually_exclusive.py -h usage: argparse_mutually_exclusive.py [-h] [-a | -b] optional arguments: -h, --help show this help message and exit -a -b $ python argparse_mutually_exclusive.py -a Namespace(a=True, b=False) $ python argparse_mutually_exclusive.py -b Namespace(a=False, b=True) $ python argparse_mutually_exclusive.py -a -b usage: argparse_mutually_exclusive.py [-h] [-a | -b] argparse_mutually_exclusive.py: error: argument -b: not allowed with argument -a
version2
import argparse parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help='commands') # A list command list_parser = subparsers.add_parser('list', help='List contents') list_parser.add_argument('dirname', action='store', help='Directory to list') # A create command create_parser = subparsers.add_parser('create', help='Create a directory') create_parser.add_argument('dirname', action='store', help='New directory to create') create_parser.add_argument('--read-only', default=False, action='store_true', help='Set permissions to prevent writing to the directory', ) # A delete command delete_parser = subparsers.add_parser('delete', help='Remove a directory') delete_parser.add_argument('dirname', action='store', help='The directory to remove') delete_parser.add_argument('--recursive', '-r', default=False, action='store_true', help='Remove the contents of the directory, too', ) print parser.parse_args(['list', 'a s d', ]) >>> Namespace(dirname='a s d') print parser.parse_args(['list', 'a s d', 'create' ]) >>> error: unrecognized arguments: create
For all the abilities and options in argparse
I don't think you'll ever get a "canned" usage string that looks like what you want.
That said, have you looked at sub-parsers since your original post?
Here's a barebones implementation:
import argparse parser = argparse.ArgumentParser(prog='mydaemon') sp = parser.add_subparsers() sp_start = sp.add_parser('start', help='Starts %(prog)s daemon') sp_stop = sp.add_parser('stop', help='Stops %(prog)s daemon') sp_restart = sp.add_parser('restart', help='Restarts %(prog)s daemon') parser.parse_args()
Running this with the -h
option yields:
usage: mydaemon [-h] {start,stop,restart} ... positional arguments: {start,stop,restart} start Starts mydaemon daemon stop Stops mydaemon daemon restart Restarts mydaemon daemon
One of the benefits of this approach is being able to use set_defaults
for each sub-parser to hook up a function directly to the argument. I've also added a "graceful" option for stop
and restart
:
import argparse def my_stop(args): if args.gracefully: print "Let's try to stop..." else: print 'Stop, now!' parser = argparse.ArgumentParser(prog='mydaemon') graceful = argparse.ArgumentParser(add_help=False) graceful.add_argument('-g', '--gracefully', action='store_true', help='tries to terminate the process gracefully') sp = parser.add_subparsers() sp_start = sp.add_parser('start', help='Starts %(prog)s daemon') sp_stop = sp.add_parser('stop', parents=[graceful], description='Stops the daemon if it is currently running.', help='Stops %(prog)s daemon') sp_restart = sp.add_parser('restart', parents=[graceful], help='Restarts %(prog)s daemon') # Hook subparsers up to functions sp_stop.set_defaults(func=my_stop) # Uncomment when my_start() and # my_restart() are implemented # # sp_start.set_defaults(func=my_start) # sp_restart.set_defaults(func=my_restart) args = parser.parse_args() args.func(args)
Showing the "help" message for stop
:
$ python mydaemon.py stop -h usage: mydaemon stop [-h] [-g] Stops the daemon if it is currently running. optional arguments: -h, --help show this help message and exit -g, --gracefully tries to terminate the process gracefully
Stopping "gracefully":
$ python mydaemon.py stop -g Let's try to stop...
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