Disable unique prefix matches for argparse and optparse

When I use the parsar Python command line argument argparse or optparse, any unique argument prefix is ​​considered valid, for example.

$ ./buildall.py --help usage: buildall.py [-h] [-f] Build all repositories optional arguments: -h, --help show this help message and exit -f, --force Build dirty repositories 

works with --help , --hel , --he for the help option, as well as --forc and --fo for the force parameter.

Is there any way to disable this behavior? I want to get an error for incomplete arguments.

+6
python argparse optparse
source share
2 answers

The ability to disable shortened long options was added only in Python 3.5. From the argparse :

The default method parse_args() allows long parameters to be reduced to a prefix if the abbreviation is unique (the prefix corresponds to a unique option) ... This function can be disabled by setting allow_abbrev to False .

So, if you are on Python 3.5, you can create your parser with allow_abbrev=False :

 parser = argparse.ArgumentParser(..., allow_abbrev=False) 

If you are on optparse or pre-3.5 argparse, you just need to live with shorthand options.

+7
source share

Prior to Python 3.5, you would have to secure the undocumented ArgumentParser method. Do not actually use this; it is not tested and may not work with all versions (or any version) of Python. For entertainment purposes only.

 import argparse # This is a copy from argparse.py, with a single change def _get_option_tuples(self, option_string): result = [] # option strings starting with two prefix characters are only # split at the '=' chars = self.prefix_chars if option_string[0] in chars and option_string[1] in chars: if '=' in option_string: option_prefix, explicit_arg = option_string.split('=', 1) else: option_prefix = option_string explicit_arg = None for option_string in self._option_string_actions: # === This is the change === # if option_string.startswith(option_prefix): if option_string == option_prefix: action = self._option_string_actions[option_string] tup = action, option_string, explicit_arg result.append(tup) # single character options can be concatenated with their arguments # but multiple character options always have to have their argument # separate elif option_string[0] in chars and option_string[1] not in chars: option_prefix = option_string explicit_arg = None short_option_prefix = option_string[:2] short_explicit_arg = option_string[2:] for option_string in self._option_string_actions: if option_string == short_option_prefix: action = self._option_string_actions[option_string] tup = action, option_string, short_explicit_arg result.append(tup) elif option_string.startswith(option_prefix): action = self._option_string_actions[option_string] tup = action, option_string, explicit_arg result.append(tup) # shouldn't ever get here else: self.error(_('unexpected option string: %s') % option_string) # return the collected option tuples return result argparse.ArgumentParser._get_option_tuples = _get_option_tuples p = argparse.ArgumentParser() p.add_argument("--foo") print p.parse_args("--f 5".split()) 
+3
source share

All Articles