Необязательные аргументы Python без тире, но с дополнительными параметрами?

В Python я бы хотел принять аргументы следующего формата:

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

Другими словами,

  1. Я не хочу иметь дело с дефисами;
  2. У меня есть несколько возможностей, одна из которых требуется;
  3. Каждый является взаимоисключающим;
  4. Некоторые из команд (EG moveabs и moverel) имеют дополнительные обязательные аргументы, но эти аргументы и не должны присутствовать с каким-либо другим аргументом.

Можно ли это сделать в Python, и я бы использовал argparse или что-то еще? Благодарю.

2 ответа

Решение

add_parser с подпарсаторами

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)

производя такие:

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

а также

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

а также

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

Аргументы MOVEREL могут быть названы <x> а также <y>, но тогда вам придется получить к ним доступ через args['<y>'] вместо args.y, metavar='<x>' может использоваться для изменения отображения, но не имени пространства имен.

Вы также можете использовать spp.add_argument('point', nargs=2, type=float), К сожалению, есть ошибка, которая не позволяет нам использовать метавар в этом nargs=2 case, http://bugs.python.org/issue14074.

С помощью docopt Вы можете сделать это довольно легко.

устанавливать docopt первый:

$ pip install docopt

Написать 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

и запустить его:

сначала показывает основную помощь:

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

затем попробуйте подкоманды:

Начните

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

стоп

$ 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}
Другие вопросы по тегам