Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

842 questions

1,291 réponses

3,064 commentaires

2,173 utilisateurs

argparse : surcharge de parse_args() ?

+1 vote

je cherche a recuperer un object à partir de deux arguments.

Surcharger parse_args est-il une bonne piste ?

class DocOnErrorArgumentParser(argparse.ArgumentParser):
    "show help on error"
    def error(self, message):
        sys.stderr.write('error: %s\n' % message)
        self.print_help()
        sys.exit(2)

class Optim(DbApp):
    def __init__(self):
        def get_password():
            if sys.stdout.isatty():
                return getpass("password:")
            else:
                raise NotImplementedError()

        def ask(question, default=None):
            if sys.stdout.isatty():
                return input(question)

            return default

        parser = DocOnErrorArgumentParser()

        parser.add_argument(
                "base",
                help="base a optimiser",
                nargs='?',
                default=ask("base:")
                )

        parser.add_argument(
                "table",
                help="table a optimiser", 
                nargs='?', 
                default=ask("table:"))

        parser.add_argument(
                "champ", 
                help="champ a optimiser", 
                nargs='?', 
                default=ask("champ:", ""))

       self.args = parser.parse_args()
demandé 17-Fev-2015 par juke (318 points)
edité 17-Fev-2015 par juke

Pourrait-on avoir un exemple de code, des explications plus concrètes ?

Si j'ai bien compris, tu veux récupérer un objet rentré par l'utilisateur en ligne de commande ? Quel type d'objet ?

je veux construire un objet ColumnSelection (de ma composition) à partir des trois arguments.

Peux-tu donner un exemple d'instanciation de ton objet sans passer par des arguments provenant de la ligne de commande ?

Et peux-tu préciser la question ? C'est quoi que tu ne parviens pas à faire ? Tu as juste à parser les arguments et à les passer au constructeur, non ?

J'arrive à le faire, mais je ne trouve pas ça particulierement élégant. d'où mon idée de surcharger le parser, pour mutualiser un peu le code et renvoyer un nouveau "type d'argument"

2 Réponses

+2 votes
 
Meilleure réponse

Pourquoi ne pas passer un type à ton add_argument ?

Un exemple qui récupère une IPv4, je veux m'assurer qu'elle soit valide
et privée. En Python 2, ipaddr fait le job, autant le laisser bosser, ça m'évite d'écrire une regex pour argparse et de convertir ensuite.

>>> import argparse
>>> import ipaddr

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('ip', type=ipaddr.IPv4Address, help="IPv4")

Avec une IP valide :

>>> args = parser.parse_args(['192.168.1.1'])
Namespace(ip=IPv4Address('192.168.1.1'))
>>> type(args.ip)
<class 'ipaddr.IPv4Address'>
>>> args.ip.is_private
True

Une IP pas valide :

>>> args = parser.parse_args(['658.184.487.985'])
usage: ipython [-h] IPv4
ipython: error: argument IPv4: invalid IPv4Address value: '658.184.487.985'
répondu 23-Fev-2015 par Geoffrey (146 points)
sélectionné 24-Fev-2015 par juke

parce que le type resultant n'est pas 1 argument mais le resultat de plusieures arguments.

Typiquement je voudrait avoir un object connection à partir des arguments host login, password.

Dans ce cas une méthode de classe me semble plus élégante que de surcharger la stdlib, ça permet de s'adapter au contexte :

class Optim(DbApp):

    def __init__(self, base, table, champ, password=None):
        self.base = base
        self.table = table
        self.champ = champ
        self.password = password

    @classmethod
    def from_argv(cls, args=None):
        parser = argparse.ArgumentParser()
        parser.add_argument('base')
        parser.add_argument('table')
        parser.add_argument('champ')

        namespace = parser.parse_args(args or sys.argv[1:])
        # A ce stade, faire des manipulations...

        # Retourner une instance de l'objet.
        return cls(**vars(namespace))

    @classmethod
    def from_env(cls, prefix):
        pass

    @classmethod
    def from_file(cls, path):
        pass


if __name__ == '__main__':

    optim = Optim.from_argv()
–1 vote

je ne suis pas sur d'avoir bien saisi ta question...
Concernant le parsing d'argument, je pense que beaucoup a été fait, et que tu dois pouvoir trouver chaussure à ton pied sans avoir à surcharger un librairie déjà bien fournie.

je te conseil vivement d'aller le post de Sam : La plus belle manière de parser les arguments de script en python...

répondu 18-Fev-2015 par Lhassa (798 points)
...