How to parse multiple nested sub-commands using python argparse?

后端 未结 11 1101
执念已碎
执念已碎 2020-11-28 20:52

I am implementing a command line program which has interface like this:

cmd [GLOBAL_OPTIONS] {command [COMMAND_OPTS]} [{command [COMMAND_OPTS]} ...]
<         


        
11条回答
  •  自闭症患者
    2020-11-28 21:45

    Improving on the answer by @mgilson, I wrote a small parsing method which splits argv into parts and puts values of arguments of commands into hierarchy of namespaces:

    import sys
    import argparse
    
    
    def parse_args(parser, commands):
        # Divide argv by commands
        split_argv = [[]]
        for c in sys.argv[1:]:
            if c in commands.choices:
                split_argv.append([c])
            else:
                split_argv[-1].append(c)
        # Initialize namespace
        args = argparse.Namespace()
        for c in commands.choices:
            setattr(args, c, None)
        # Parse each command
        parser.parse_args(split_argv[0], namespace=args)  # Without command
        for argv in split_argv[1:]:  # Commands
            n = argparse.Namespace()
            setattr(args, argv[0], n)
            parser.parse_args(argv, namespace=n)
        return args
    
    
    parser = argparse.ArgumentParser()
    commands = parser.add_subparsers(title='sub-commands')
    
    cmd1_parser = commands.add_parser('cmd1')
    cmd1_parser.add_argument('--foo')
    
    cmd2_parser = commands.add_parser('cmd2')
    cmd2_parser.add_argument('--foo')
    
    cmd2_parser = commands.add_parser('cmd3')
    cmd2_parser.add_argument('--foo')
    
    
    args = parse_args(parser, commands)
    print(args)
    

    It behaves properly, providing nice argparse help:

    For ./test.py --help:

    usage: test.py [-h] {cmd1,cmd2,cmd3} ...
    
    optional arguments:
      -h, --help        show this help message and exit
    
    sub-commands:
      {cmd1,cmd2,cmd3}
    

    For ./test.py cmd1 --help:

    usage: test.py cmd1 [-h] [--foo FOO]
    
    optional arguments:
      -h, --help  show this help message and exit
      --foo FOO
    

    And creates a hierarchy of namespaces containing the argument values:

    ./test.py cmd1 --foo 3 cmd3 --foo 4
    Namespace(cmd1=Namespace(foo='3'), cmd2=None, cmd3=Namespace(foo='4'))
    

提交回复
热议问题