Как составить несколько подкоманд и использовать команду по умолчанию, используя argparse? - PullRequest
0 голосов
/ 15 мая 2018

В моем примере ниже я пытаюсь настроить следующие сценарии командной строки:

$ myapp.py flowers [-h]
$ myapp.py flowers plants [-h]
$ myapp.py flowers plants add [-h]

Фактические результаты:

$ python myapp.py flowers
usage: myapp.py flowers [-h] {plants} ...
myapp.py flowers: error: too few arguments
$ python myapp.py flowers plants
usage: myapp.py flowers plants [-h] [--format {plain,json}] {add} ...
myapp.py flowers plants: error: too few arguments
$ python myapp.py flowers plants add
Adding flowers...  The input format is expected to be plain

Проблема заключается во втором сценарии.Я намерен сделать так, чтобы это была неявная операция со списком.Как это сделать?

Вот исходный код моего примера.

import sys
import argparse

def _flowers_plants_list(args):
    print('if this were real, the output format would be %s' % (args.format))       
    print('Here are all the flowers:')
    print('flower 1: rose')
    print('flower 2: tulip')
    print('flower 3: daisy')

def _flowers_plants_add(args):
    print('Adding flowers...  The input format is expected to be %s' % (args.format))

def main():
    # myapp.py
    parser_main = argparse.ArgumentParser()
    subparsers_main = parser_main.add_subparsers()

    # myapp.py flowers [-h]
    parser_flowers = subparsers_main.add_parser("flowers")
    subparsers_flowers = parser_flowers.add_subparsers()

    # (this is supposed to be an implicit list - NOT WORKING)
    # myapp.py flowers plants [-h]
    parser_flowers_plants = subparsers_flowers.add_parser("plants")
    parser_flowers_plants.add_argument("--format", default='plain', choices=['plain', 'json'], help="what format should the result be in")
    parser_flowers_plants.set_defaults(func=_flowers_plants_list)
    subparsers_flowers_plants = parser_flowers_plants.add_subparsers()

    # myapp.py flowers plants add [-h]
    parser_flowers_plants_add = subparsers_flowers_plants.add_parser("add")
    parser_flowers_plants_add.add_argument("--format", default='plain', choices=['plain', 'json'], help="what format will the input be in")
    parser_flowers_plants_add.set_defaults(func=_flowers_plants_add)

    args = parser_main.parse_args()
    r = args.func(args)
    return r

if __name__ == "__main__":
    sys.exit(main())

1 Ответ

0 голосов
/ 16 мая 2018

В Py3:

1420:~/mypy$ python3 stack50350537.py 
Traceback (most recent call last):
  File "stack50350537.py", line 40, in <module>
    sys.exit(main())
  File "stack50350537.py", line 36, in main
    r = args.func(args)
AttributeError: 'Namespace' object has no attribute 'func'
1421:~/mypy$ python3 stack50350537.py flowers
Traceback (most recent call last):
  File "stack50350537.py", line 40, in <module>
    sys.exit(main())
  File "stack50350537.py", line 36, in main
    r = args.func(args)
AttributeError: 'Namespace' object has no attribute 'func'
1421:~/mypy$ python3 stack50350537.py flowers plants
if this were real, the output format would be plain
Here are all the flowers:
flower 1: rose
flower 2: tulip
flower 3: daisy
1422:~/mypy$ python3 stack50350537.py flowers plants add
Adding flowers...  The input format is expected to be plain

В py2 требуются подпарсеры:

1423:~/mypy$ python2 stack50350537.py
usage: stack50350537.py [-h] {flowers} ...
stack50350537.py: error: too few arguments
1423:~/mypy$ python2 stack50350537.py flowers
usage: stack50350537.py flowers [-h] {plants} ...
stack50350537.py flowers: error: too few arguments
1423:~/mypy$ python2 stack50350537.py flowers plants
usage: stack50350537.py flowers plants [-h] [--format {plain,json}] {add} ...
stack50350537.py flowers plants: error: too few arguments
1423:~/mypy$ python2 stack50350537.py flowers plants add
Adding flowers...  The input format is expected to be plain

В Py3 подпарсеры не требуются.Первоначально это изменение было ошибкой, возникшей в результате изменения способа тестирования required.Но так было достаточно долго, что теперь это особенность.Существует шаг к тому, чтобы предоставить пользователям немного больше контроля над этой функцией, но я думаю, что not required останется по умолчанию.

Argparse с необходимым подпаратором

...