如何有一个特定的子命令需要带有 argparse 的标志?

Posted

技术标签:

【中文标题】如何有一个特定的子命令需要带有 argparse 的标志?【英文标题】:How to have a specific sub-command require flag with argparse? 【发布时间】:2020-03-22 06:35:12 【问题描述】:

所以我正在编写一个使用argparse 的python 脚本来传递信息和处理输入。我一直在使用子命令来强制/使用程序中的不同操作。到目前为止,我的脚本格式如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse

def main(username, password, api, apiId):
    print("Hello, world!")

def _cli():
    # Create parser to obtain arguments
    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter, argument_default=argparse.SUPPRESS)
    subparsers = parser.add_subparsers(dest = "api", required = True)
    base_subparser = argparse.ArgumentParser(add_help = False)
    # Shared arguments
    base_subparser.add_argument('-u', '--username', help = "Username", default = "admin")
    base_subparser.add_argument('-p', '--password', help = "Password", default = "admin")

    # Create subcommands
    create_parser = subparsers.add_parser("create", parents = [base_subparser])
    update_parser = subparsers.add_parser("update", parents = [base_subparser])

    # Flag for sub-parser to pass API ID
    update_parser.add_argument('-i', '--apiId', help = "ID for API you are trying to access.", required = True)

    # Obtain all the argument values
    args = parser.parse_args()

    # Return them in a dictionary format
    return vars(args)

if __name__ == '__main__':
    # Pass arguments to main function using dictonary format.
    main(**_cli())

在哪里指定用法:

用法:test.py [-h] create,update ...

位置参数: 创建、更新

可选参数: -h, --help 显示此帮助信息并退出

我的问题是,虽然 update 命令工作正常,但我需要传递一个 ID,但我的 create 有一个错误/问题,它抱怨没有设置标志/传递一个,即使它是不需要/不需要。

main(**_cli())
TypeError: main() missing 1 required positional argument: 'apiId'

我在这里做错了什么,我该如何解决?我试过谷歌,但我似乎无法理解问题/如何解决它。

【问题讨论】:

【参考方案1】:

您收到的错误是告诉您在使用create 子命令时未提供apiId。您可以指定一个默认参数,如下所示:

def main(username, password, api, apiId=None):
    print("API: ".format(api))
    print("API ID: ".format(apiId))
~ python args.py create -u a -p b
API: create
API ID: None
~ python args.py update -u a -p b -i c
API: update
API ID: c

或者您可以在函数定义中使用 ** 扩展来获得关键字参数的 dict

def main(**kwds):
    print(kwds)
~ python args.py create -u a -p b
'api': 'create', 'username': 'a', 'password': 'b'
~ python args.py update -u a -p b -i c
'api': 'update', 'username': 'a', 'password': 'b', 'apiId': 'c'

【讨论】:

非常感谢!效果很好!作为参考,我选择了选项 1。 这也是我的首选。 ?

以上是关于如何有一个特定的子命令需要带有 argparse 的标志?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python argparse 解析多个嵌套的子命令?

argparse:如何允许带有 nargs="*" 和选项的空列表

在 argparse 中有一个带有破折号的选项

带有子命令的命令和子命令请求的 argparse 解决方案

argparse 子命令和组:在自己的组上的子命令中设置帮助对话框,而不隐藏在***帮助对话框中

带有通用子解析器命令的 Python argparse