Argument Parser Python 条件要求

Argument Parser Python conditional requirement

我有一个维护联系人列表的 Python 程序,我希望它通过命令行支持以下选项:

  1. --show ,接受一个字符串参数
  2. --list ,不带参数
  3. --add ,接受一个字符串参数
  4. --number ,接受一个 int 参数
  5. --email ,接受一个字符串参数

我需要的是:

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)

问题是我不想通过命令行提供我想使用的子解析器的 number/name。

例如:

prog.py 1 --list
prog.py 2 --add xyz --number 1234 --email abc@xyz.com

我试图让它与 mutually_exclusive_group 一起工作,但不能。有没有办法绕过这种用法?

您真的需要在命令前加上双短划线 (--) 吗? 如果没有,你可以这样做:

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 xyzprog add 123 但你不能做 prog show xzy add 123.

对于这类事情,我通常更喜欢 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.

您可以像这样使用 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