web-dev-qa-db-fra.com

Python: Comment rendre une option obligatoire dans optparse?

J'ai lu ceci http://docs.python.org/release/2.6.2/library/optparse.html

Mais je ne sais pas trop comment faire une option qui sera requise dans l'optparse?

J'ai essayé de définir "required = 1" mais j'ai une erreur:

arguments de mots clés non valides: requis

Je veux que mon script nécessite --file option à saisir par les utilisateurs. Je sais que le mot clé action vous donne une erreur lorsque vous ne fournissez pas de valeur à --file dont action="store_true".

36
jack

Vous pouvez facilement implémenter une option requise.

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')
64
user225312

Sur le message d'aide de chaque variable requise En écrivant une chaîne '[REQUIRED]' au début, pour la marquer pour être analysée plus tard, alors je peux simplement utiliser cette fonction pour la boucler:

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)
10
Fausto Luiz Santin

Puisque if not x ne fonctionne pas pour certains paramètres (négatifs, zéro),

et pour éviter de nombreux tests if, je préfère quelque chose comme ceci:

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)
7
Serge M.

L'actuel réponse avec le plus de votes ne fonctionnerait pas si, par exemple, l'argument était un entier ou un flottant pour lequel zéro est une entrée valide. Dans ces cas, il dirait qu'il y a une erreur. Une alternative (à ajouter aux autres ici) serait de faire par exemple.

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')
4
Matt Pitkin

Je suis obligé d'utiliser python 2.6 pour notre solution, je m'en tiens donc au module optparse. Voici la solution que j'ai trouvée pour vérifier les options requises qui fonctionnent sans spécifier la deuxième fois la liste des options requises. Ainsi, lorsque vous ajoutez une nouvelle option, vous n'avez pas à ajouter son nom dans la liste des options à vérifier.

Mes critères pour l'option requise - la valeur de l'option ne doit pas être None et cette option n'a pas de valeur par défaut (l'utilisateur n'a pas spécifié 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
3
vvladymyrov

Il existe au moins deux méthodes d'implémentation des options requises avec optparse. Comme mentionné dans la page docs , optparse ne vous empêche pas d'implémenter les options requises, mais ne vous donne pas grand-chose aider à elle non plus. Retrouvez ci-dessous les exemples trouvés dans les fichiers distribués avec la source.

Bien que veuillez noter que optparse module est obsolète depuis la version 2.7 et ne sera pas développé davantage. Vous devez utiliser argparse module à la place.


Version 1: ajoutez à OptionParser une méthode que les applications doivent appeler après l'analyse des arguments:

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")

La source: docs/lib/required_1.txt


Version 2: étendre l'option et ajouter un attribut requis; étendez OptionParser pour vous assurer que les options requises sont présentes après l'analyse:

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

La source: docs/lib/required_2.txt

1
kenorb

Comme le module optparse est obsolète depuis la version 2.7, vous trouverez probablement des exemples plus à jour ici: n exemple d'argparse simple et simple voulait: 1 argument, 3 résultats

0
PatriceG

Je suis également bloqué sur python 2.6 (pining pour python2.7 et argparse, qui non seulement a des arguments requis, mais me permet de spécifier que l'un d'un ensemble doit être fourni); mon approche nécessite une deuxième passe, mais me permet de demander les arguments manquants, sauf en cas d'exécution en mode batch:

# 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

(Je pense à créer ma propre classe d'analyseur qui a des options communes pour les configurations globales intégrées.)

Une autre réponse à cette question a cité parser.error, que je ne connaissais pas lorsque j'ai écrit le code, mais qui aurait pu être un meilleur choix.

0
arp