如何使用 argparse python 为两个类别设置不同的强制参数?

Posted

技术标签:

【中文标题】如何使用 argparse python 为两个类别设置不同的强制参数?【英文标题】:How to have different mandatory parameters for two categories using argparse python? 【发布时间】:2021-03-07 18:13:05 【问题描述】:

我正在编写 python 脚本,我需要根据传递的输入参数做两件事:

push:这将调用一个 api 来发布一些数据。 status:这将调用另一个api来检查数据并在控制台上打印出详细信息。

当我们使用push参数时,我们需要始终传递这三个强制参数:

环境 实例 配置

而当我们使用status参数时,我们只需要传递这两个强制参数:

环境 实例

如何在 Python 中使用 argparse 以这种方式配置这些参数?我正在阅读有关此here 的更多信息,但对如何使上述内容以良好的方式工作感到困惑?使用信息也应该清楚地说明使用什么输入。

使用argparse 可以做到这一点吗?任何示例将不胜感激。一般来说,我们会为push 调用一个方法,该方法将使用这些参数,类似地,对于status,我们将调用其他一些将使用这些参数的方法。

【问题讨论】:

是的,我认为您想在“argparse”模块中使用“子命令”。这是指向涵盖它们的文档部分的指针。这可能与您在上面链接的相同文档(可能不同版本)中,但它会将您带到子命令部分:docs.python.org/3/library/argparse.html#sub-commands 就个人而言,在有人对可能重复这个或重复那个感到高兴之前,这是我第一次看到 argparse 子命令的一个明确的简约示例,它不仅仅是“参考文档”或者,相反,写一本关于它的小说。 【参考方案1】:

这是一个简单的例子,它使用带有两个子命令的 argparse:

"""
How to have different mandatory parameters for two categories
using argparse python?
"""
import argparse
import sys

def main():
    """
    Description here
    """
    parser = argparse.ArgumentParser(
        description='Stack Overflow 64995368 Parser'
    )
    parser.add_argument(
        "-v",
        "--verbose",
        help="verbose output",
        action="store_true"
    )
    subparser = parser.add_subparsers(
        title="action",
        dest='action',
        required=True,
        help='action sub-command help'
    )

    # create the subparser for the "push" command
    parser_push = subparser.add_parser(
        'push',
        help='push help'
    )
    parser_push.add_argument(
        'environment',
        type=str,
        help='push environment help'
    )
    parser_push.add_argument(
        'instance',
        type=str,
        help='push instance help'
    )
    parser_push.add_argument(
        'config',
        type=str,
        help='push config help'
    )

    # create the subparser for the "status" command
    parser_status = subparser.add_parser(
        'status',
        help='status help'
    )
    parser_status.add_argument(
        'environment',
        type=str,
        help='status environment help'
    )
    parser_status.add_argument(
        'instance',
        type=str,
        help='status instance help'
    )

    args = parser.parse_args()

    if args.action == 'push':
        print('You chose push:',
            args.environment, args.instance, args.config)
    elif args.action == 'status':
        print('You chose status:',
            args.environment, args.instance)
    else:
        print('Something unexpected happened')

if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        print("\nCaught ctrl+c, exiting")

各种命令行的示例输出:

$ python3 test.py
usage: test.py [-h] [-v] push,status ...
test.py: error: the following arguments are required: action

$ python3 test.py -h
usage: test.py [-h] [-v] push,status ...

Stack Overflow 64995368 Parser

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  verbose output

action:
  push,status  action sub-command help
    push         push help
    status       status help

$ python3 test.py push -h
usage: test.py push [-h] environment instance config

positional arguments:
  environment  push environment help
  instance     push instance help
  config       push config help

optional arguments:
  -h, --help   show this help message and exit

$ python3 test.py push
usage: test.py push [-h] environment instance config
test.py push: error: the following arguments are required: environment, instance, config

$ python3 test.py push myenv
usage: test.py push [-h] environment instance config
test.py push: error: the following arguments are required: instance, config

【讨论】:

【参考方案2】:

您可以这样做,使用set_defaults 为每个子命令分配一个处理程序。

import argparse

def push(args):
    return (args.environment, args.instance, args.config)

def status(args):
    return (args.environment, args.instance)

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers()

# create the parser for the push command
push_parser = subparsers.add_parser('push')
push_parser.set_defaults(func=push)

push_parser.add_argument('--environment', type=str)
push_parser.add_argument('--instance', type=str)
push_parser.add_argument('--config', type=str)


# create the parser for the status command
status_parser = subparsers.add_parser('status')
status_parser.set_defaults(func=status)

status_parser.add_argument('--environment', type=str)
status_parser.add_argument('--instance', type=str)

    
args = parser.parse_args(['push', '--environment=a', '--instance=b', '--config=c'])
print(args.func(args))

【讨论】:

【参考方案3】:

直接使用 sys.argv 内容通常更容易。 https://www.tutorialspoint.com/python/python_command_line_arguments.htm

#! /usr/bin/env python3

import sys
s_args  = sys .argv  ##  s_args[0] = script_name.py

def push( environment,  instance,  config ):
    print( 'PUSH command:',  environment,  instance,  config )

def status( environment,  instance ):
    print( 'STATUS command:',  environment,  instance )

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if __name__ == '__main__':
    if len( s_args ) < 4:
        print( 'missing args:' )
        print( '    PUSH environment instance config' )
        print( '    STATUS environment instance' )

    elif s_args[1] .lower() == 'push':
        if len( s_args ) < 5:
            print( 'missing args for PUSH command:' )
            print( '    PUSH environment instance config' )
        else:
            push( s_args[2],  s_args[3],  s_args[4] )

    elif s_args[1] .lower() == 'status':
        if len( s_args ) < 4:
            print( 'missing args for STATUS command:' )
            print( '    STATUS environment instance' )
        else:
            status( s_args[2],  s_args[3] )

    else:
        print( 'incorrect command:' )
        print( '    PUSH environment instance config' )
        print( '    STATUS environment instance' )

【讨论】:

以上是关于如何使用 argparse python 为两个类别设置不同的强制参数?的主要内容,如果未能解决你的问题,请参考以下文章

类定义中的 Python argparse 命名空间

如何根据 Python 中的位置参数与 argparse 的组合设置不同的选项?

python argparse - 要么两个可选参数,要么一个都没有

Python:argparse 帮助文本的分页?

与两个连接的 python3 脚本一起使用时的 argparse 冲突

如何使用 argparse Python 在 SQL 查询中传递日期范围参数