Необязательные аргументы Python без тире, но с дополнительными параметрами?
В Python я бы хотел принять аргументы следующего формата:
script.py START | STOP | STATUS | MOVEABS <x> <y> | MOVEREL <x> <y>
Другими словами,
- Я не хочу иметь дело с дефисами;
- У меня есть несколько возможностей, одна из которых требуется;
- Каждый является взаимоисключающим;
- Некоторые из команд (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}