Search code examples
pythonargparse

How can I set up argparse to parse either 'diff -g file1 -r file2' or 'format file'?


I want to use argparse to parse command line arguments for my program. The program supports two modes - diff and format.

When -diff is chosen, the arguments -g <file1> and -r <file2> are also needed. When -format is chosen, instead there should be a <file> argument.

How can I set up this logic with argparse? Should I use subparsers?


Solution

  • Just to share and record what I have finalized eventually. There are two solutions that I tried and eventually I picked up the subparser one although I think both ways work well to suit this task:

    1. Using subparser
    import argparse
    
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='command')
    subparsers.required = True
    
    # subparser for diff
    parser_multi = subparsers.add_parser('diff')
    # add required arguments
    parser_diff.add_argument(
        '-f1',
        '--file1',
        type=str,
        required=True
    )
    parser_diff.add_argument(
        '-f2',
        '--file2',
        type=str,
        required=True
    )
    
    # subparser for format
    parser_format = subparsers.add_parser('format')
    # add a required argument
    parser_format.add_argument(
        '-f',
        '--file',
        type=str,
        required=True
    )
    
    args = parser.parse_args()
    
    1. Using conditional args parser
    import argparse
    import sys
    
    mode_choices = ['diff', 'format']
    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--mode',
                        choices=mode_choices,
                        help='Choose mode to start',
                        required=True)
    
    if True in list(map(lambda x: mode_choices[0] in x, sys.argv)):
        parser.add_argument('-f1',
                            '--file1',
                            type=str,
                            required=True)
        parser.add_argument('-f2',
                            '--file2',
                            type=str,
                            required=True)
    
    if True in list(map(lambda x: mode_choices[1] in x, sys.argv)):
        parser.add_argument('-f',
                            '--file',
                            type=str,
                            required=True)
    
    args = parser.parse_args()