1 """Parser for command line options.
3 This module helps scripts to parse the command line arguments in
4 sys.argv. It supports the same conventions as the Unix getopt()
5 function (including the special meanings of arguments of the form `-'
6 and `--'). Long options similar to those supported by GNU software
7 may be used as well via an optional third argument. This module
8 provides two functions and an exception:
10 getopt() -- Parse command line options
11 gnu_getopt() -- Like getopt(), but allow option and non-option arguments
13 GetoptError -- exception (class) raised with 'opt' attribute, which is the
14 option involved with the exception.
17 # Long option support added by Lars Wirzenius <liw@iki.fi>.
19 # Gerrit Holl <gerrit@nl.linux.org> moved the string-based exceptions
20 # to class-based exceptions.
22 # Peter Åstrand <astrand@lysator.liu.se> added gnu_getopt().
24 # TODO for gnu_getopt():
26 # - GNU getopt_long_only mechanism
27 # - allow the caller to specify ordering
28 # - RETURN_IN_ORDER option
29 # - GNU extension with '-' as first character of option string
30 # - optional arguments, specified by double colons
31 # - an option string with a W followed by semicolon should
32 # treat "-W foo" as "--foo"
34 __all__ = ["GetoptError","error","getopt","gnu_getopt"]
38 from gettext import gettext as _
40 # Bootstrapping Python: gettext's dependencies not built yet
43 class GetoptError(Exception):
46 def __init__(self, msg, opt=''):
49 Exception.__init__(self, msg, opt)
54 error = GetoptError # backward compatibility
56 def getopt(args, shortopts, longopts = []):
57 """getopt(args, options[, long_options]) -> opts, args
59 Parses command line options and parameter list. args is the
60 argument list to be parsed, without the leading reference to the
61 running program. Typically, this means "sys.argv[1:]". shortopts
62 is the string of option letters that the script wants to
63 recognize, with options that require an argument followed by a
64 colon (i.e., the same format that Unix getopt() uses). If
65 specified, longopts is a list of strings with the names of the
66 long options which should be supported. The leading '--'
67 characters should not be included in the option name. Options
68 which require an argument should be followed by an equal sign
71 The return value consists of two elements: the first is a list of
72 (option, value) pairs; the second is the list of program arguments
73 left after the option list was stripped (this is a trailing slice
74 of the first argument). Each option-and-value pair returned has
75 the option as its first element, prefixed with a hyphen (e.g.,
76 '-x'), and the option argument as its second element, or an empty
77 string if the option has no argument. The options occur in the
78 list in the same order in which they were found, thus allowing
79 multiple occurrences. Long and short options may be mixed.
84 if type(longopts) == str:
87 longopts = list(longopts)
88 while args and args[0].startswith(b'-') and args[0] != '-':
92 if args[0].startswith(b'--'):
93 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
95 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
99 def gnu_getopt(args, shortopts, longopts = []):
100 """getopt(args, options[, long_options]) -> opts, args
102 This function works like getopt(), except that GNU style scanning
103 mode is used by default. This means that option and non-option
104 arguments may be intermixed. The getopt() function stops
105 processing options as soon as a non-option argument is
108 If the first character of the option string is `+', or if the
109 environment variable POSIXLY_CORRECT is set, then option
110 processing stops as soon as a non-option argument is encountered.
116 if isinstance(longopts, str):
117 longopts = [longopts]
119 longopts = list(longopts)
121 # Allow options after non-option arguments?
122 if shortopts.startswith(b'+'):
123 shortopts = shortopts[1:]
124 all_options_first = True
125 elif os.environ.get("POSIXLY_CORRECT"):
126 all_options_first = True
128 all_options_first = False
132 prog_args += args[1:]
135 if args[0][:2] == '--':
136 opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
137 elif args[0][:1] == '-' and args[0] != '-':
138 opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
140 if all_options_first:
144 prog_args.append(args[0])
147 return opts, prog_args
149 def do_longs(opts, opt, longopts, args):
155 opt, optarg = opt[:i], opt[i+1:]
157 has_arg, opt = long_has_args(opt, longopts)
161 raise GetoptError(_('option --%s requires argument') % opt, opt)
162 optarg, args = args[0], args[1:]
163 elif optarg is not None:
164 raise GetoptError(_('option --%s must not have an argument') % opt, opt)
165 opts.append(('--' + opt, optarg or ''))
171 def long_has_args(opt, longopts):
172 possibilities = [o for o in longopts if o.startswith(opt)]
173 if not possibilities:
174 raise GetoptError(_('option --%s not recognized') % opt, opt)
175 # Is there an exact match?
176 if opt in possibilities:
178 elif opt + '=' in possibilities:
180 # No exact match, so better be unique.
181 if len(possibilities) > 1:
182 # XXX since possibilities contains all valid continuations, might be
183 # nice to work them into the error msg
184 raise GetoptError(_('option --%s not a unique prefix') % opt, opt)
185 assert len(possibilities) == 1
186 unique_match = possibilities[0]
187 has_arg = unique_match.endswith('=')
189 unique_match = unique_match[:-1]
190 return has_arg, unique_match
192 def do_shorts(opts, optstring, shortopts, args):
193 while optstring != '':
194 opt, optstring = optstring[0], optstring[1:]
195 if short_has_arg(opt, shortopts):
198 raise GetoptError(_('option -%s requires argument') % opt,
200 optstring, args = args[0], args[1:]
201 optarg, optstring = optstring, ''
204 opts.append(('-' + opt, optarg))
207 def short_has_arg(opt, shortopts):
208 for i in range(len(shortopts)):
209 if opt == shortopts[i] != ':':
210 return shortopts.startswith(b':', i+1)
211 raise GetoptError(_('option -%s not recognized') % opt, opt)
213 if __name__ == '__main__':
215 print(getopt(sys.argv[1:], "a:b", ["alpha=", "beta"]))