How to handle CLI subcommands with argparse

前端 未结 2 1201
囚心锁ツ
囚心锁ツ 2020-12-10 07:03

I need to implement a command line interface in which the program accepts subcommands.

For example, if the program is called “foo”, the CLI would look like



        
2条回答
  •  难免孤独
    2020-12-10 07:19

    First of all subparsers are never inserted in the namespace. In the example you posted if you try to run the script as:

    $python3 test_args.py cmd1 1
    Namespace(cmd1_option1='1')
    

    where test_args.py contain the code you provided (with the import argparse at the beginning and print(args) at the end).

    Note that there is no mention to cmd1 only to its argument. This is by design.

    As pointed out in the comments you can add that information passing the dest argument to the add_subparsers call.

    The usual way to handle these circumstances is to use the set_defaults method of the subparsers:

    import argparse
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(help='Functions')
    parser_1 = subparsers.add_parser('cmd1', help='...')
    parser_1.add_argument('cmd1_option1', type=str, help='...')
    parser_1.set_defaults(parser1=True)
    
    parser_2 = subparsers.add_parser('cmd2', help='...')
    parser_2.set_defaults(parser2=True)
    
    parser_3 = subparsers.add_parser('cmd3', help='...')
    parser_3.add_argument('cmd3_options', type=int, help='...')
    parser_3.set_defaults(parser_3=True)
    
    args = parser.parse_args()
    print(args)
    

    Which results in:

    $python3 test_args.py cmd1 1
    Namespace(cmd1_option1='1', parser1=True)
    $python3 test_args.py cmd2
    Namespace(parser2=True)
    

    In general different subparser will, most of the time, handle the arguments in completely different ways. The usual pattern is to have different functions to run the different commands and use set_defaults to set a func attribute. When you parse the arguments you simply call that callable:

    subparsers = parser.add_subparsers()
    parser_1 = subparsers.add_parser(...)
    parser_1.set_default(func=do_command_one)
    
    parser_k = subparsers.add_parser(...)
    parser_k.set_default(func=do_command_k)
    
    args = parser.parse_args()
    if args.func:
        args.func(args)
    

提交回复
热议问题