Pergunta

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.

Foi útil?

Solução

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 "************************"

Outras dicas

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')
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top