Search code examples
pythonpython-3.xgetoptcommand-line-arguments

parse command line arguments not reading all arguments?


So, I came across the getopt module to parse command line args, although I can't make any sense of the docs. For whatever reason, I cannot figure out why this isn't seeing my --domain example.com argument..

$ ./httpdsetup.py -a -u zack --domain example.com
[('-a', ''), ('-u', '')]

I printed out what gets dumped into opts to see what it saw. The code below is just about an exact duplicate from the documentation site.

def main(argv):
        import getopt

        try:
                opts, args = getopt.getopt(argv, "h:al:ud:v", ["user=", "apache", "lighttpd", "dir=", "domain=", "vhost="])
        except getopt.GetoptError:
                print_usage()
                sys.exit(2)

        username = ''
        directory = ''
        domain = ''

        httpd = 'apache'

        print(opts)

        for opt, arg in opts:
                if opt == '-h':
                        print_usage()
                        sys.exit()
                elif opt in ('-u', '--username'):
                        username = arg
                elif opt in ('-d', '--dir'):
                        directory = arg
                elif opt in ('-v', '--domain', '--vhost'):
                        domain = arg
                elif opt in ('-a', '--apache'):
                        httpd = 'apache'
                elif opt in ('-l', '--lighttpd'):
                        httpd = 'lighttpd'
                else:
                        print_usage()
                        sys.exit()

        if httpd == 'apache':
                create_apache_vhost(domain, directory, username)
        elif httpd == 'lighttpd':
                create_lighty_vhost(domain, directory, username)

if __name__ == '__main__':
        main(sys.argv[1:])

Solution

  • I prefer argparse. Python documention here. It's in Python >=2.7 and >=3.2, but not in Python 3.0 and 3.1. If it's missing in your install, just copy the single file from here to where your script is, or into your Python install.

    Here's something close to your example with argparse:

    #!/usr/bin/env python3
    
    import sys
    
    
    
    def create_apache_vhost(*args, **kwargs):
        pass
    
    def create_lighty_vhost(*args, **kwargs):
        pass
    
    def main(argv):
            import argparse
    
            parser = argparse.ArgumentParser(description="Some server",
                                             formatter_class=argparse.RawDescriptionHelpFormatter)
    
            parser.add_argument('--username', type=str)
            parser.add_argument('-u', dest='username', type=str)
    
            parser.add_argument('--apache', dest='httpd', action='store_const', const='apache')
            parser.add_argument('-a',       dest='httpd', action='store_const', const='apache')
            parser.add_argument('--lighthttpd', dest='httpd', action='store_const', const='lighthttpd')
            parser.add_argument('-l',           dest='httpd', action='store_const', const='lighthttpd')
    
            parser.add_argument('--domain', type=str)
            parser.add_argument('--vhost',  type=str)
            parser.add_argument('-v', dest='domain', type=str)
    
            parser.add_argument('--dir', dest='directory', type=str)
            parser.add_argument('-d', dest='directory', type=str)
    
            defaults = {
                'httpd': 'apache',
                }
            parser.set_defaults(**defaults)
    
            args = parser.parse_args(args=argv)
    
            print(args)
    
            if args.httpd == 'apache':
                    create_apache_vhost(args.domain, args.directory, args.username)
            elif args.httpd == 'lighttpd':
                    create_lighty_vhost(args.domain, args.directory, args.username)
    
    if __name__ == '__main__':
            main(sys.argv[1:])