parser - Python: ¿Cómo hacer una opción para ser requerida en optparse?
parser python example (9)
Como el módulo optparse está en desuso desde la versión 2.7, probablemente encontrará algunos ejemplos más actualizados aquí: Ejemplo de argparse muerto simple deseado: 1 argumento, 3 resultados
Leí este http://docs.python.org/release/2.6.2/library/optparse.html
Pero no estoy tan claro cómo hacer una opción para ser requerida en optparse?
Intenté establecer "required = 1" pero recibí un error:
argumentos inválidos de palabra clave: requeridos
Quiero que mi script requiera --file
opción de --file
sea ingresada por los usuarios. Sé que la palabra clave action
le da error cuando no proporciona valor a --file
cuya action="store_true"
.
Dado que if not x
no funciona para algunos parámetros (negativo, cero),
y para evitar muchas pruebas si, 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)
En el mensaje de ayuda de cada variable requerida estoy escribiendo una cadena ''[REQUERIDO]'' al principio, para etiquetarla para que sea analizada más tarde, entonces 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)
Estoy obligado a usar Python 2.6 para nuestra solución, así que me quedo con el módulo optparse. Aquí hay una solución que encontré para verificar las opciones requeridas que funcionan sin especificar una segunda lista de opciones requeridas. Por lo tanto, cuando agrega una nueva opción, no tiene que agregar su nombre en la lista de opciones para verificar.
Mi criterio para la opción requerida - el valor de la opción no debe ser None y esta opción no tiene el valor predeterminado (el usuario no especificó add_option (default = "...", ...).
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
Hay al menos dos métodos para implementar las opciones requeridas con optparse
. Como se menciona en la página de documentos , optparse no impide que implemente las opciones requeridas, pero tampoco le brinda mucha ayuda. Encuentre a continuación 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 cual 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: amplíe 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
La respuesta actual con la mayoría de los votos no funcionaría si, por ejemplo, el argumento fuera un 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'')
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'')
También estoy atascado en Python 2.6 (pining para python2.7 y argparse, que no solo tiene argumentos obligatorios, sino que también me permite especificar que se debe proporcionar uno de un conjunto); mi enfoque requiere un segundo pase, pero me permite pedir 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 crear 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.
Utilizaría la biblioteca argparse que tiene esta funcionalidad incrustada:
PARSER.add_argument("-n", "--namespace", dest="namespace", required=True,
help="The path within the repo to the data base")