Pergunta

what I'd like to do in Python is accept arguments of the following format:

script.py START | STOP | STATUS | MOVEABS <x> <y> | MOVEREL <x> <y>

So in other words,

  1. I don't want to deal with hyphens;
  2. I have multiple possibilities, ONE of which is required;
  3. Each is mutually exclusive;
  4. Some of the commands (E.G. moveabs and moverel) have additional required arguments, but these args and should not be present with any other argument.

Can this be done in python and would I use argparse or something else? Thanks.

Foi útil?

Solução

add_parser with subparsers would do the trick

import argparse
parser = argparse.ArgumentParser(prog='script.py')
sp = parser.add_subparsers(dest='cmd')
for cmd in ['START', 'STOP', 'STATUS']:
    sp.add_parser(cmd)
for cmd in ['MOVEABS', 'MOVEREL']:
    spp = sp.add_parser(cmd)
    spp.add_argument('x', type=float)
    spp.add_argument('y', type=float)
parser.print_help()
args = parser.parse_args()
print(args)

producing the likes of:

2137:~/mypy$ python2.7 stack23304740.py MOVEREL -h
usage: script.py [-h] {START,STOP,STATUS,MOVEABS,MOVEREL} ...

positional arguments:
  {START,STOP,STATUS,MOVEABS,MOVEREL}

optional arguments:
  -h, --help            show this help message and exit

usage: script.py MOVEREL [-h] x y

positional arguments:
  x
  y

optional arguments:
  -h, --help  show this help message and exit

and

2146:~/mypy$ python2.7 stack23304740.py MOVEREL 1.0 2.0
...
Namespace(cmd='MOVEREL', x=1.0, y=2.0)

and

2147:~/mypy$ python2.7 stack23304740.py START
...
Namespace(cmd='START')

The MOVEREL arguments could be named <x> and <y>, but then you'd have to access them via args['<y>'] instead of args.y. metavar='<x>' could be used to change the display but not the Namespace name.

You could also use spp.add_argument('point', nargs=2, type=float). Unfortunately there's a bug that keeps us from using a metavar in this nargs=2 case, http://bugs.python.org/issue14074.

Outras dicas

Using docopt you can do this quite easily.

Install docopt first:

$ pip install docopt

Write the script.py:

"""
Usage:
    script.py (start | stop | status | moveabs <x> <y> | moverel <x> <y>)
"""
from docopt import docopt

if __name__ == "__main__":
    args = docopt(__doc__)
    print args

and run it:

first showing basic help:

$ python script.py
Usage:
    script.py (start | stop | status | moveabs <x> <y> | moverel <x> <y>)

then try subcommands:

start

$ python script.py start
{'<x>': None,
 '<y>': None,
 'moveabs': False,
 'moverel': False,
 'start': True,
 'status': False,
 'stop': False}

stop

$ python script.py stop
{'<x>': None,
 '<y>': None,
 'moveabs': False,
 'moverel': False,
 'start': False,
 'status': False,
 'stop': True}

moveabs

$ python script.py moveabs 11 22
{'<x>': '11',
 '<y>': '22',
 'moveabs': True,
 'moverel': False,
 'start': False,
 'status': False,
 'stop': False}

moverel

$ python script.py moverel 11 22
{'<x>': '11',
 '<y>': '22',
 'moveabs': False,
 'moverel': True,
 'start': False,
 'status': False,
 'stop': False}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top