Аргумент Parser Python условное требование - PullRequest
0 голосов
/ 16 сентября 2018

У меня есть программа на Python, которая поддерживает список контактов, и я хочу, чтобы она поддерживала следующие параметры через командную строку:

  1. - show , принимает строковый аргумент
  2. - список , не принимает аргументов
  3. - добавить , принимает аргумент строки
  4. -число , принимает аргумент int
  5. - электронная почта , принимает аргумент строки

Что мне нужно:

prog [--show xyz | --list | --add xyz --number 123 --email abcd@xyz.com ]

Я пытался реализовать его с помощью подпарасеров следующим образом:

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

subparser1 = subparsers.add_parser('1')
subparser1.add_argument('--show', type=str, help="Shows the contact based on the given name provided as argument")
subparser1.add_argument('--list', action='store_true', help= "Prints all the contacts")

subparser2 = subparsers.add_parser('2')

subparser2.add_argument('--add', type=str, help="Adds a new contact by this name",required=True)
subparser2.add_argument('--number', type=int, help="The Phone Number for the new contact",required=True)
subparser2.add_argument('--email', type=str, help="Email address for the new contact",required=True)

Проблема в том, что я не хочу указывать номер / имя подпаратера, через который я хочу использоватькомандной строки.

Например:

prog.py 1 - списокprog.py 2 --add xyz --number 1234 --email abc@xyz.com

Я пытался заставить его работать с mutually_exclusive_group , но не смог.Есть ли способ обойти это использование?

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Я обычно предпочитаю библиотеку click для такого рода вещей.Ваш пример (без -- перед командами) можно сделать так:

Код:

import click

@click.group()
def cli():
    """My Cool Tool"""


@cli.command()
@click.argument('name')
def show(name):
    """Shows the contact based on the given name provided as argument"""
    click.echo('Show me some cool things about {}'.format(name))


@cli.command('list')
def list_cmd():
    """Prints all the contacts"""
    click.echo('Here are some contacts')


@cli.command()
@click.argument('name')
@click.option('--number', required=True, help='The Phone Number for the new contact')
@click.option('--email', required=True, help='Email address for the new contact')
def add(name, number, email):
    """Adds a new contact by this name"""
    click.echo('Name: {}'.format(name))
    click.echo('Number: {}'.format(number))
    click.echo('Email: {}'.format(email))

Код теста:

if __name__ == "__main__":
    commands = (
        'show a_name',
        'list',
        'add a_name --number 123 --email e@mail',
        '',
        'show --help',
        'list --help',
        'add --help',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

Результаты теста:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> show a_name
Show me some cool things about a_name
-----------
> list
Here are some contacts
-----------
> add a_name --number 123 --email e@mail
Name: a_name
Number: 123
Email: e@mail
-----------
> 
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  My Cool Tool

Options:
  --help  Show this message and exit.

Commands:
  add   Adds a new contact by this name
  list  Prints all the contacts
  show  Shows the contact based on the given name...
-----------
> show --help
Usage: test.py show [OPTIONS] NAME

  Shows the contact based on the given name provided as argument

Options:
  --help  Show this message and exit.
-----------
> list --help
Usage: test.py list [OPTIONS]

  Prints all the contacts

Options:
  --help  Show this message and exit.
-----------
> add --help
Usage: test.py add [OPTIONS] NAME

  Adds a new contact by this name

Options:
  --number TEXT  The Phone Number for the new contact  [required]
  --email TEXT   Email address for the new contact  [required]
  --help         Show this message and exit.
0 голосов
/ 16 сентября 2018

Вы можете использовать метод add_mutually_exclusive_group следующим образом:

from argparse import ArgumentParser

parser = ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--show', help='...', action='store_true')
group.add_argument('--list', help='...', action='store_true')
group.add_argument('--add',  type=str, help='...')

parser.add_argument("--number", type=int, required=False)
parser.add_argument("--email", type=str, required=False)

args = parser.parse_args()

if args.add:
    # proceed with args.number and args.email
else:
    # ignore args.number and args.email...

Выход:

$ python test.py
usage: test.py [-h] (--show | --list | --add ADD) [--number NUMBER]
               [--email EMAIL]
test.py: error: one of the arguments --show --list --add is required
0 голосов
/ 16 сентября 2018

Вам действительно нужна двойная черта (--) перед вашей командой?Если нет, вы можете сделать:

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='command')

show_subparser = subparsers.add_parser('show')
show_subparser.add_argument('name', type=str)

list_subparser = subparsers.add_parser('list')

add_subparser = subparsers.add_parser('add')
add_subparser.add_argument('phone', type=int)

args = parser.parse_args()

# Do something with your args
print args

Это ограничит вас определенными выше аргументами.Поскольку вы можете сделать prog show xyz или prog add 123, но вы не можете prog show xzy add 123.

...