Преобразуйте многие аргументы argparse в более питонное решение - PullRequest
0 голосов
/ 14 ноября 2018

Я работаю над приложением cli, использующим python.У меня есть набор аргументов, которые являются взаимоисключающими, и набор аргументов, которые должны присутствовать, если передан один из этих взаимоисключающих аргументов.
У меня все работает, используя грубую силу и длительные условия if, но я чувствуюкак есть аккуратный способ сделать это.Изучение этого сказало, что subparsers может быть полезно, однако я не могу правильно использовать subparsers .
Я хочу следующие условия:
Основные виды деятельности
+ ----- + -------- + -------- + -------- + -------- +
|получить |создать |удалить |обновление |удалить |
+ ----- + -------- + -------- + -------- + --------- +

Эти основные виды деятельности взаимоисключающие .

Если указано get , то аргументов не должно быть больше.
Если указано delete , то должно не больше никаких аргументов.
Если указано удалить , то -r является обязательным .
Если update указано тогда-f обязательный , а -cd - необязательный .
Если указано create , то -d - обязательный -m и -f являются необязательными , где -m и -f являются взаимоисключающими .

Код грубой силы выглядит следующим образом -

import argparse
parser = argparse.ArgumentParser(description='Check args')
#get
parser.add_argument('-g', '--get', help='')
#create
parser.add_argument('-c', '--create', help='')
parser.add_argument('-d', '--display', help='')
parser.add_argument('-m', '--message', help='')
parser.add_argument('-f', '--file', help='')
#update
parser.add_argument('-u', '--update', help='')
parser.add_argument('-cd', '--changed', help='')
#delete
parser.add_argument('-del', '--delete', help='')
#remove
parser.add_argument('-rm', help='')
parser.add_argument('-r', '--remove', help='')

args = vars(parser.parse_args())

if args['get'] is not None:
    if args['create'] is None and args['display'] is None and args['message'] is None and args['file'] is None and args['update'] is None and args['changed'] is None and args['delete'] is None and args['rm'] is None and args['remove'] is None:
        print(args['get'])
    else:
        print('Dont mix get with others')
        exit()

if args['create']:
    if args['get'] is None and args['message'] is None and args['file'] is None and args['update'] is None and args['changed'] is None and args['delete'] is None and args['rm'] is None and args['remove'] is None:
        print(args['create'])
    else:
        print('Dont mix create with others')
        exit()
    if args['display'] is None:
        print('Missing display')

if args['update']:
    if args['get'] is None and args['create'] is None and args['display'] is None and args['message'] is None and args['delete'] is None and args['rm'] is None and args['remove'] is None:
        print(args['update'])
    else:
        print('Dont mix update with others')
        exit()
    if args['file'] is None:
        print('Missing file')

if args['delete']:
    if args['get'] is None and args['create'] is None and args['display'] is None and args['message'] is None and args['file'] is None and args['update'] is None and args['changed'] is None and args['rm'] is None and args['remove'] is None:
        print(args['delete'])
    else:
        print('Dont mix delete with others')
        exit()

if args['rm']:
    if args['get'] is None and args['create'] is None and args['display'] is None and args['message'] is None and args['file'] is None and args['update'] is None and args['changed'] is None and args['delete'] is None:
        print(args['rm'])
    else:
        print('Dont mix resource management with others')
        exit()
    if args['remove'] is None:
        print('Missing remove')

Есть ли способ сделать его более питоническим?

РЕДАКТИРОВАТЬ 1:
Почему я не включил код, используя subparser ?
Потому что, насколько я понял, подпарсеры сами по себе не берут никакогоценности.Так что в моем случае я хочу иметь возможность выполнить скрипт следующим образом -

  • prog -g xxyy
  • prog -c xxyy -d 'Hello World'
  • prog -u xxyy -f 'file.md' -cd 'Foo bar baz'

Где при использовании подпарсеров они могут стать чем-то вроде (что я не хочу, поправьте меня, если я ошибаюсь ) -

  • prog get -g xxyy
  • prog create -c xxyy -d 'Hello World'

РЕДАКТИРОВАТЬ 2
Я понял, как использовать взаимоисключающие аргументы, используя add_mutually_exclusive_group

parser = argparse.ArgumentParser(description='Mutex')
group = parser.add_mutually_exclusive_group()
group.add_argument('-g')
group.add_argument('-c')
group.add_argument('-u')
group.add_argument('-del')
group.add_argument('-rm')

РЕДАКТИРОВАТЬ 3
Я не могу получить работу subparse .Следующий код (работающий с подмножеством) выдает ошибку error: invalid choice: 'world' (choose from '-m', '-f'), если команда $ python3 parse2.py -c hello -m world

parser = argparse.ArgumentParser(description='Mutex')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-g')
group.add_argument('-c')
subparser = parser.add_subparsers()
parser_a = subparser.add_parser('-m')
parser_b = subparser.add_parser('-f')
args = parser.parse_args()
print(args)

EDIT 4
Я почти решил мою проблему сследующее -

import argparse
parser = argparse.ArgumentParser()
sp = parser.add_subparsers(dest='main') # , required=True) in Py3.7
sp.required = True    # in py 3.6
p1 = sp.add_parser('get')
p1.add_argument('id')

p2 = sp.add_parser('update')
p2.add_argument('id')
p2.add_argument('-f', required=True)
p2.add_argument('-cd')

p3 = sp.add_parser('create')
p3.add_argument('name')
p3.add_argument('-d', required=True)
p3_mutex = p3.add_mutually_exclusive_group()
p3_mutex.add_argument('-f')
p3_mutex.add_argument('-m')

p4 = sp.add_parser('delete')
p4.add_argument('id')

p5 = sp.add_parser('remove')
p5.add_argument('id')
p5.add_argument('-r', required=True)

args = parser.parse_args()
print(args)

Однако я хочу знать, возможно ли добавить add_mutually_exclusive_group для get, delete, create, update и remove или у меня естьсделать это, используя if условия?

1 Ответ

0 голосов
/ 15 ноября 2018

Начало версии подпарсера:

import argparse
parser = argparse.ArgumentParser()
sp = parser.add_subparsers(dest='main') # , required=True) in Py3.7
sp.required = True    # in py 3.6
p1 = sp.add_parser('get')
p1.add_argument('xxyy')

p2 = sp.add_parser('update')
p2.add_argument('xxyy')
p2.add_argument('-r', required=True)
p2.add_argument('--cd')
# and so forth
args = parser.parse_args()
print(args)

примерные прогоны

0914:~/mypy$ python3 stack53307678.py -h
usage: stack53307678.py [-h] {get,update} ...

positional arguments:
  {get,update}

optional arguments:
  -h, --help    show this help message and exit
0914:~/mypy$ python3 stack53307678.py get abc
Namespace(main='get', xxyy='abc')
0914:~/mypy$ python3 stack53307678.py update abc -r foo --cd x
Namespace(cd='x', main='update', r='foo', xxyy='abc')
...