2015-11-24 9 views
6

Quando utilizzo il parser di argomenti della riga di comando argparse o optparse di Python, qualsiasi prefisso univoco di un argomento è considerato valido, ad es.Disabilita le corrispondenze prefissate univoche per argparse e optparse

$ ./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 

opere con --help, --hel, --he per l'opzione di aiuto così come --forc e --fo per l'opzione forza.

Questo comportamento può essere disattivato in qualche modo? Voglio ricevere un messaggio di errore per argomenti incompleti.

risposta

7

La possibilità di disabilitare le opzioni lunghe abbreviate è stata aggiunta solo in Python 3.5. Dal argparse documentation:

Il metodo di parse_args()di default permette lunghe opzioni da abbreviati a un prefisso, se la sigla è ambigua (il prefisso corrisponde a una possibilità unica) ... Questa funzione può essere disabilitata impostazione allow_abbrev a False.

Quindi, se siete in Python 3.5, è possibile creare il parser con allow_abbrev=False:

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

Se siete su optparse o pre-3.5 argparse, devi solo vivere con abbreviato opzioni.

+0

Grande, sai di un'opzione analogica per optparse? –

+0

@SimonWarta: No. C'è un motivo per cui è deprecato. – user2357112

+2

Nota che 'allow_abbrev' non è disponibile prima di Python 3.5. – chepner

3

Prima di Python 3.5, è necessario monkeypatch un metodo ArgumentParser non documentato. In realtà non usare questo; non è testato e potrebbe non funzionare con tutte le versioni (o qualsiasi versione) di Python. Solo a scopo di intrattenimento.

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()) 
+0

Il cambiamento non è molto grande - se sei disposto a modificare il coraggio del tuo 'argparse.py'. Se vuoi che il comportamento sia commutabile avrai più modifiche per passare una sorta di parametro switch. – hpaulj