You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python argparse实现带末尾可选多值参数的子命令

用argparse实现带末尾可选位置参数的子命令

需求:实现命令格式 script.py {scan,list} ... [targets [targets...]],要求两个子命令scan和list都拥有可选的、位于末尾的位置参数(设置nargs=*)。

已尝试的方法及问题

方法1:使用父解析器共享targets参数

  • 问题:
    • 主脚本帮助信息(script.py -h)不显示targets参数,仅显示 [-h] {scan,list} ...,而非预期的 [-h] {scan,list} ... [targets [targets...]]
    • proxy参数会被置于targets之后,无法保证targets始终在末尾
  • 代码:
parser = argparse.ArgumentParser()
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('targets', type=str, nargs='*', default="ALL")

subparsers = parser.add_subparsers()

parser_scan = subparsers.add_parser('scan', parents=[parent_parser])
parser_scan.add_argument('proxy', type=str)

parser_list = subparsers.add_parser('list', parents=[parent_parser])

方法2:手动为每个子解析器添加targets参数

  • 问题:
    • 主脚本帮助信息仍不显示targets参数
    • 若为主解析器添加targets参数(取消注释第3行),会覆盖子解析器的同名参数,导致args.targets始终返回默认值"ALL"
  • 代码:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
# parser.add_argument('targets', type=str, nargs='*', default="ALL")

parser_scan = subparsers.add_parser('scan')
parser_scan.add_argument('proxy', type=str)
parser_scan.add_argument('targets', type=str, nargs='*', default="ALL")

parser_list = subparsers.add_parser('list')
parser_list.add_argument('targets', type=str, nargs='*', default="ALL")

方法3:仅在主解析器添加targets参数

  • 问题:
    • 主脚本帮助信息显示正确,但运行script.py list Target1时报错:
      usage: target-utils.py [-h] {scan,list} ... [targets [targets ...]]
      target-utils.py: error: unrecognized arguments: Target1
      
  • 代码:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
parser.add_argument('targets', type=str, nargs='*', default="ALL")

parser_scan = subparsers.add_parser('scan')
parser_scan.add_argument('proxy', type=str)

parser_list = subparsers.add_parser('list')

解决方案

核心思路:

  1. 子解析器中先添加专属参数,再添加targets参数,确保targets在末尾
  2. 手动自定义主解析器的usage,让帮助信息显示targets参数
  3. 为子解析器设置dest,确保能正确区分子命令

完整代码:

import argparse

def main():
    # 自定义主解析器的usage,明确显示targets参数
    parser = argparse.ArgumentParser(
        usage="%(prog)s {scan,list} ... [targets [targets...]]"
    )
    subparsers = parser.add_subparsers(dest="command", required=True)

    # 定义scan子命令:先加proxy参数,再加targets(末尾)
    parser_scan = subparsers.add_parser('scan')
    parser_scan.add_argument('proxy', type=str, help="Proxy server address")
    parser_scan.add_argument(
        'targets', 
        type=str, 
        nargs='*', 
        default="ALL", 
        help="Optional target list (default: ALL)"
    )

    # 定义list子命令:直接加targets参数
    parser_list = subparsers.add_parser('list')
    parser_list.add_argument(
        'targets', 
        type=str, 
        nargs='*', 
        default="ALL", 
        help="Optional target list (default: ALL)"
    )

    args = parser.parse_args()
    print(f"Command: {args.command}")
    print(f"Targets: {args.targets}")
    if args.command == "scan":
        print(f"Proxy: {args.proxy}")

if __name__ == "__main__":
    main()

验证效果

  1. 主帮助信息(script.py -h)显示正确:
    usage: script.py {scan,list} ... [targets [targets...]]
    
    positional arguments:
      {scan,list}
    
    optional arguments:
      -h, --help  show this help message and exit
    
  2. scan子命令帮助(script.py scan -h):
    usage: script.py scan [-h] proxy [targets ...]
    
    positional arguments:
      proxy       Proxy server address
      targets     Optional target list (default: ALL)
    
    optional arguments:
      -h, --help  show this help message and exit
    
  3. 运行测试:
    • script.py list Target1 Target2:输出Targets: ['Target1', 'Target2']
    • script.py scan http://proxy.com TargetA:输出Proxy: http://proxy.com和Targets: ['TargetA']
    • script.py list:输出Targets: ALL

内容的提问来源于stack exchange,提问作者Keanu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:45:34