Reputation: 91820
I'm making a pretty simple script which takes the following parameters:
-p --port integer, optional, default 5050
-f --fork boolean, optional, default False
action string, required, needs to be either start or stop
I've tried implementing this in argparse, but it's not printing help when action string isn't provided, it's just failing all ugly-like:
usage: __init__.py [-h] [-p PORT] [-f] {start,stop}
__init__.py: error: argument action: invalid choice: '__init__.py' (choose from 'start', 'stop')
Even when I pass "start" or "stop", it fails with the same message. Here's my code:
parser = argparse.ArgumentParser(description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n")
parser.add_argument("-p", "--port", type=int, nargs=1, default=5050,
dest="port", help="The port to run the server on.")
parser.add_argument("-f", "--fork", action="store_true", default=False,
dest="fork", help="Fork to background? Default is false.")
parser.add_argument("action", type=str, choices=("start","stop"), help="Whether to 'start' or 'stop' the server.")
What am I doing wrong here? Hopefully my intentions are pretty clear from my code.
Upvotes: 1
Views: 2674
Reputation: 28046
What version of Python are you using? When I run your code with 2.7.1 it works fine.
$ ./t stop
$ ./t start
$ ./t -f start
$ ./t -f stop
$ ./t -f
usage: someprog [-h] [-p PORT] [-f] {start,stop}
someprog: error: too few arguments
$ ./t -f -p 8080
usage: someprog [-h] [-p PORT] [-f] {start,stop}
someprog: error: too few arguments
$ ./t -f -p 8080 start
One tip, if you specify 'prog' in the ctor you can override it using init.py as the filename
parser = argparse.ArgumentParser(
prog="someprog",
description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n"
)
Also, it is printing usage, but not the long help.. You could do something like this to make things a little more obvious..
try:
parser.parse_args()
except Exception e:
print "************************"
parser.print_help()
print "************************"
Upvotes: 1
Reputation: 19339
When invalid arguments are supplied, the argparse module is designed to print a usage message and a description of the problem then exit, which is precisely what is happening in your example.
If you want it to print a help message instead, you'll need to handle this case yourself. For example, this code will print the help message in the event that no action is provided:
parser = argparse.ArgumentParser(description="Start or stop the server.",
epilog="If you don't know what you're doing, run. Run for your life.\n",
prog="myserver")
parser.add_argument("-p", "--port", type=int, nargs=1, default=5050,
dest="port", help="The port to run the server on.")
parser.add_argument("-f", "--fork", action="store_true", default=False,
dest="fork", help="Fork to background? Default is false.")
parser.add_argument("action", nargs="?", type=str, choices=("start","stop"),
help="Whether to 'start' or 'stop' the server.")
args = parser.parse_args()
if args.action is None:
parser.print_help()
sys.exit(1)
If I run this with no action, I get:
$ python s.py
usage: myserver [-h] [-p PORT] [-f] [{start,stop}]
Start or stop the server.
positional arguments:
{start,stop} Whether to 'start' or 'stop' the server.
optional arguments:
-h, --help show this help message and exit
-p PORT, --port PORT The port to run the server on.
-f, --fork Fork to background? Default is false.
If you don't know what you're doing, run. Run for your life.
However, if I run this with an invalid action, or an invalid argument, then it reverts to the intended behaviour of the argparse module:
$ python s.py not_valid
usage: myserver [-h] [-p PORT] [-f] [{start,stop}]
myserver: error: argument action: invalid choice: 'not_valid' (choose from 'start', 'stop')
Upvotes: 2