Search code examples
pythoncommand-line-argumentsgetopt

python getopt module raise error when argument is not behind an option


I have the a piece of code to handle command line arguments.

def parse_cmd_args():
    input_path = None
    output_name = 'out.flv.txt'
    is_detail = False
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hi:o:d")
    except getopt.GetoptError:
        print 'Usage:'
        print 'parse_flv -i input_path -o [output_name]'
        sys.exit()
    for op, value in opts:
        if op == '-i':
            input_path = value
        elif op == '-o':
            output_name = value
        elif op == '-d':
            is_detail = True
        elif op == '-h':
            print 'Usage:'
            print 'parse_flv -i input_path [-o output_name]'
            sys.exit()
    return os.path.abspath(input_path), output_name, is_detail

If I input a command without a option symbol '-' like this:

 python parse_flv.py s

It will raise an error.

MY QUESTION:

How to handle arguments without a '-i' like option using getopt module. Thanks


Solution

  • You should consider using argparse module instead. getopt is kind of limited...

    This module is a lot more handy (less code and more informative help and error messages). In your case this would simply be something like:

    parser = argparse.ArgumentParser(add_help=True)
    parser.add_argument('infile', nargs=1, help='input file name')
    parser.add_argument('outfile', nargs='?', help='output file name')
    

    In this example, outfile would be optional and you could specify a default output file name:

    parser.add_argument('outfile', nargs='?', help='output file name', default='out.txt')
    

    More details about both getopt and argparse here (compared to each other).


    EDIT :

    Here is the best one can do with getopt (as far as I read), i.e. switch to GNU mode using gnu_getopt:

    import getopt
    import sys
    
    output_name = 'out.txt'
    input_name = ''
    
    print 'ARGV      :', sys.argv[1:]
    
    options, remainder = getopt.gnu_getopt(sys.argv[1:], 'o:', ['input-path',
                                                               'output-name=',
                                                              ])
    print 'OPTIONS   :', options
    
    for opt, arg in options:
        if opt in ('-o', '--output-name'):
            output_name = arg
        else: 
            pass
    
    # Get input name by yourself...
    input_name = remainder[0]
    
    print 'OUTPUTNAME  :', output_name
    print 'REMAINING   :', remainder
    print 'INPUTNAME   :', input_name
    

    Calling:

    python parse_flv.py input -o output
    

    or

    python parse_flv.py -o output input
    

    outputs:

    ARGV      : ['-o', 'output', 'input']
    OPTIONS   : [('-o', 'output')]
    OUTPUTNAME  : output
    REMAINING   : ['input']
    INPUTNAME   : input
    

    which would confirm that you then have to deal with the remaining list by yourself...

    But, at least, you can switch the order of the two options.

    Interesting source here.