Python: ¿Cómo hacer que una opción sea requerida en optparse?

He leído esto http://docs.python.org/release/2.6.2/library/optparse.html

¿Pero no estoy tan claro cómo hacer que una opción sea requerida en optparse?

He intentado configurar “requerido = 1” pero obtuve un error:

argumentos de palabra clave inválida: requerido

Quiero que mi script requiera la opción --file para que los usuarios la --file . Sé que la palabra clave action te da un error cuando no le --file valor a --file cuya action="store_true" .

Puede implementar una opción requerida fácilmente.

 parser = OptionParser(usage='usage: %prog [options] arguments') parser.add_option('-f', '--file', dest='filename', help='foo help') (options, args) = parser.parse_args() if not options.filename: # if filename is not given parser.error('Filename not given') 

En el mensaje de ayuda de cada variable requerida Im que escribe una cadena ‘[REQUERIDA]’ al principio, para etiquetarla y analizarla más tarde, simplemente puedo usar esta función para envolverla:

 def checkRequiredArguments(opts, parser): missing_options = [] for option in parser.option_list: if re.match(r'^\[REQUIRED\]', option.help) and eval('opts.' + option.dest) == None: missing_options.extend(option._long_opts) if len(missing_options) > 0: parser.error('Missing REQUIRED parameters: ' + str(missing_options)) parser = OptionParser() parser.add_option("-s", "--start-date", help="[REQUIRED] Start date") parser.add_option("-e", "--end-date", dest="endDate", help="[REQUIRED] End date") (opts, args) = parser.parse_args(['-s', 'some-date']) checkRequiredArguments(opts, parser) 

Como if not x no funciona para algunos parámetros (negativos, cero),

Y para evitar muchas pruebas, prefiero algo como esto:

 required="host username password".split() parser = OptionParser() parser.add_option("-H", '--host', dest='host') parser.add_option("-U", '--user', dest='username') parser.add_option("-P", '--pass', dest='password') parser.add_option("-s", '--ssl', dest='ssl',help="optional usage of ssl") (options, args) = parser.parse_args() for r in required: if options.__dict__[r] is None: parser.error("parameter %s required"%r) 

Estoy obligado a usar Python 2.6 para nuestra solución, así que me apego al módulo optparse. Aquí está la solución que encontré para verificar las opciones requeridas que funcionan sin especificar la segunda lista de las opciones requeridas. Por lo tanto, cuando agrega una nueva opción, no tiene que agregar su nombre en la lista de opciones para verificarla.

Mis criterios para la opción requerida: el valor de la opción no debe ser Ninguno y esta opción no tiene valor predeterminado (el usuario no especificó add_option (predeterminado = “…”, …).

 def parse_cli(): """parse and check command line options, shows help message @return: dict - options key/value """ import __main__ parser = OptionParser(description=__main__.__doc__) parser.add_option("-d", "--days", dest="days", help="Number of days to process") parser.add_option("-p", "--period", dest="period_length",default="2", help="number or hours per iteration, default value=%default hours") (options, args) = parser.parse_args() """get dictionary of options' default values. in this example: { 'period_length': '2','days': None}""" defaults = vars(parser.get_default_values()) optionsdict = vars(options) all_none = False for k,v in optionsdict.items(): if v is None and defaults.get(k) is None: all_none = True if all_none: parser.print_help() sys.exit() return optionsdict 

La respuesta actual con la mayoría de los votos no funcionaría si, por ejemplo, el argumento fuera un número entero o flotante para el cual cero es una entrada válida. En estos casos diría que hay un error. Una alternativa (para agregar a los otros aquí) sería hacer, por ejemplo,

 parser = OptionParser(usage='usage: %prog [options] arguments') parser.add_option('-f', '--file', dest='filename') (options, args) = parser.parse_args() if 'filename' not in options.__dict__: parser.error('Filename not given') 

Hay al menos dos métodos para implementar las opciones requeridas con optparse . Como se mencionó en la página de documentos , optparse no le impide implementar las opciones requeridas, pero tampoco le brinda mucha ayuda. A continuación encontrará los ejemplos encontrados en los archivos distribuidos con la fuente.

Aunque tenga en cuenta que el módulo optparse está en desuso desde la versión 2.7 y no se desarrollará más. Deberías usar el módulo argparse lugar.


Versión 1: agregue un método a OptionParser al que las aplicaciones deben llamar después de analizar los argumentos:

 import optparse class OptionParser (optparse.OptionParser): def check_required (self, opt): option = self.get_option(opt) # Assumes the option's 'default' is set to None! if getattr(self.values, option.dest) is None: self.error("%s option not supplied" % option) parser = OptionParser() parser.add_option("-v", action="count", dest="verbose") parser.add_option("-f", "--file", default=None) (options, args) = parser.parse_args() print "verbose:", options.verbose print "file:", options.file parser.check_required("-f") 

Fuente: docs/lib/required_1.txt


Versión 2: Extienda la opción y agregue un atributo requerido; extienda OptionParser para asegurarse de que las opciones requeridas estén presentes después del análisis:

 import optparse class Option (optparse.Option): ATTRS = optparse.Option.ATTRS + ['required'] def _check_required (self): if self.required and not self.takes_value(): raise OptionError( "required flag set for option that doesn't take a value", self) # Make sure _check_required() is called from the constructor! CHECK_METHODS = optparse.Option.CHECK_METHODS + [_check_required] def process (self, opt, value, values, parser): optparse.Option.process(self, opt, value, values, parser) parser.option_seen[self] = 1 class OptionParser (optparse.OptionParser): def _init_parsing_state (self): optparse.OptionParser._init_parsing_state(self) self.option_seen = {} def check_values (self, values, args): for option in self.option_list: if (isinstance(option, Option) and option.required and not self.option_seen.has_key(option)): self.error("%s not supplied" % option) return (values, args) parser = OptionParser(option_list=[ Option("-v", action="count", dest="verbose"), Option("-f", "--file", required=1)]) (options, args) = parser.parse_args() print "verbose:", options.verbose print "file:", options.file 

Fuente: docs/lib/required_2.txt

También estoy atascado en Python 2.6 (pining para python2.7 y argparse, que no solo tiene argumentos necesarios, sino que también me permite especificar que se debe suministrar uno de un conjunto); mi enfoque requiere un segundo paso, pero me permite solicitar argumentos faltantes a menos que se ejecute en modo por lotes:

 # from myscript import helpers import globalconfig parser = optparse.OptionParser(usage=myheader,epilog=myfooter) parser.add_option("-L","--last", action="store",dest="last_name",default="", help="User's last (family) name; prompted for if not supplied" ) parser.add_option("-y","--yes", action="store_true",dest="batch_flag",default=False, help="don't prompt to confirm actions (batch mode)" ) [...] (options, args) = parser.parse_args() globalconfig.batchmode = options.batch_flag [...] last = prompt_if_empty(options.last_name, "Last name (can supply with \"-L\" or \"--last\" option):") # from helpers.py def prompt_if_empty(variable,promptstring): if not variable: if globalconfig.batchmode: raise Exception('Required variable missing.') print "%s" %promptstring variable = raw_input(globalconfig.prompt) return variable 

(Estoy pensando en hacer mi propia clase de analizador que tenga opciones comunes para configuraciones globales integradas).

Otra respuesta a esta pregunta citó a parser.error, con el que no estaba familiarizado cuando escribí el código, pero podría haber sido una mejor opción.

Como el módulo optparse está en desuso desde la versión 2.7, es probable que encuentre algunos ejemplos más actualizados aquí: Dead simple argparse example wanted: 1 argumento, 3 resultados

Yo usaría la biblioteca argparse que tiene esta funcionalidad incorporada:

 PARSER.add_argument("-n", "--namespace", dest="namespace", required=True, help="The path within the repo to the data base") 

referencia argparse