Comparaison des bibliothèques d'analyse de ligne de commande Python (argparse, click, fire)

Comparaison des bibliothèques d'analyse de ligne de commande Python

introduction

Cet article est le 18e jour du calendrier de l'Avent Python.

Récemment, j'utilise la ligne de commande un peu plus souvent. J'ai utilisé la valeur par défaut, argparse, mais je n'en suis pas sûr, je vais donc chercher d'autres options et les comparer. Je vais enquêter et comparer avec click, fire qui semble être populaire Je vais.

Cet article utilise les versions suivantes de la bibliothèque:

pipenv --python 3.7.5
$ pipenv install click==7.0
$ pipenv install fire==0.2.1

Outil de ligne de commande pour créer

python commands.py [command] [options] NAME

De base

$ python commands.py hello World
Hello, World
$ python commands.py hellow World
Goodbye, World

option

$ python commands.py hello --greeting=Wazzup World
Whazzup, World
$ python commands.py goodbye --greeting=Later World
Later, World
$ python commands.py hello --caps World
HELLO, WORLD
$ python commands.py hello --greeting=Wazzup --caps World
WAZZUP, WORLD

Dans cet article, nous comparerons les méthodes de chaque bibliothèque pour implémenter les fonctions suivantes le long du flux de l'article de référence.

  1. Commande (bonjour, au revoir)
  2. Argument
  3. Options / indicateurs (--greeting = \ , --caps)

Fonctionnalités supplémentaires (seront écrites plus tard)

  1. Affichage de la version
  2. Message d'aide
  3. Gestion des erreurs

commander

Je ferai l'écriture de base de diverses bibliothèques.

Argparse

import argparse

def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    hello_parser = subparsers.add_parser("hello")
    goodbye_parser = subparsers.add_parser("goodbye")
    parser.parse_args()

if __name__ == "__main__":
    main()

Vous disposez maintenant de deux commandes et d'un message d'aide intégré. Le message d'aide change lorsqu'il est exécuté en option pour la commande bonjour.

$ python argparse/commands.py --helop
usage: commands.py [-h] {hello} ...

positional arguments:
    {hello}

optional arguments:
    -h, --help  show this help message and exit
$ python commands.py hello --help
usage: commands.py hello [-h]

optional arguments:
    -h, --help  show this help message and exit

Click

import click

@click.group()
def greet():
    pass

@greet.command()
def hello(**kwargs):
    pass

@greet.command()
def goodbye(**kwargs):
    pass

if __name__ == "__main__":
    greet()

Vous disposez maintenant de deux commandes et d'un message d'aide intégré. Le message d'aide change lorsqu'il est exécuté en option pour la commande bonjour.

$ python click/commands.py  --help
Usage: commands.py [OPTIONS] COMMAND [ARGS]...

Options:
    --help  Show this message and exit.

Commands:
    goodbye
    hello

$ python click/commands.py hello --help
Usage: commands.py hello [OPTIONS]

Options:
    --help  Show this message and exit.

Fire

import fire

def hello():
    pass

def goodbye():
    pass

if __name__ == "__main__":
    fire.Fire({"hello": hello, "goodbye": goodbye})

Vous disposez maintenant de deux commandes et d'un message d'aide intégré. Le message d'aide change lorsqu'il est exécuté en option pour la commande bonjour. De plus, le feu fournit une aide au format man. Le feu peut également être mis en œuvre des manières suivantes.

--Comment organiser les fonctions

import fire

def hello():
    pass

def goodbye():
    pass

if __name__ == "__main__":
    fire.Fire()

--Comment réussir en classe

import fire

class Greet:
    def hello(self):
        pass

    def goodbye(self):
        pass

if __name__ == "__main__":
    greet = Greet()
    fire.Fire(greet)
$ python fire/commands.py --help

NAME
    commands.py

SYNOPSIS
    commands.py COMMAND

COMMANDS
    COMMAND is one of the following:
        goodbye
        hello

$ python fire/commands.py hello --help

NAME
    commands.py hello

SYNOPSIS
    commands.py hello

C'est très intéressant avec une approche différente pour chaque bibliothèque dans la bibliothèque de base. Ensuite, nous ajouterons l'argument NAME et la logique pour sortir le résultat de chaque outil.

argument

Ici, nous allons ajouter une nouvelle logique au code que nous avons écrit ci-dessus. Ajoutez un commentaire à la nouvelle ligne pour indiquer votre objectif. L'argument (spécification de position) est une entrée obligatoire. Cette fois, nous ajouterons un argument avec nom afin que l'outil puisse saluer une personne spécifique.

Argparse

Utilisez ʻadd_argumentpour ajouter un argument à une sous-commande. Puis définissez-le avecset_defautlspour exécuter la fonction. Enfin, après avoir analysé les arguments, exécutez la fonction avec ʻargs.func (args).

import argparse

def hello(args):
    print(f"Hello, {args.name}")

def goodbye(args):
    print(f"Goodbye, {args.name}")

def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    hello_parser = subparsers.add_parser("hello")
    hello_parser.add_argument("name")
    hello_parser.set_defaults(func=hello)

    goodbye_parser = subparsers.add_parser("goodbye")
    goodbye_parser.add_argument("name")
    goodbye_parser.set_defaults(func=goodbye)

    args = parser.parse_args()
    args.func(args)

if __name__ == "__main__":
    main()
$ python argparse/commands.py hello World
Hello, World

$ python argparse/commands.py hello --help
usage: commands.py hello [-h] name

positional arguments:
    name

optional arguments:
    -h, --help  show this help message and

Click

Utilisez @ click.argument pour ajouter un argument à Click. Dans ce cas, il vous suffit de passer le nom de l'argument, mais il existe plusieurs options.

$ python click/commands.py hello World
Hello, World

$ python click/commands.py hello --help
Usage: commands.py hello [OPTIONS] NAME

Options:
    --help  Show this message and exit.

Fire

Fire ajoute simplement des arguments à la fonction. Dans Fire, il s'agit essentiellement d'une implémentation de fonction / classe, donc c'est assez simple.

import fire

def hello(name):
    print(f"Hello, {name}")

def goodbye(name):
    print(f"Goodbye, {name}")

if __name__ == "__main__":
    fire.Fire({"hello": hello, "goodbye": goodbye})
$ python fire/commands.py hello World
Hello, World
(test-cli) ikura4@ikura1-ThinkPad:~/test/test-cli$ python fire/commands.py hello --help

NAME
    commands.py hello

SYNOPSIS
    commands.py hello NAME

POSITIONAL ARGUMENTS
    NAME

NOTES
    You can also use flags syntax for POSITIONAL ARGUMENTS
(END)

Options / drapeaux

Ici, nous ajouterons à nouveau la nouvelle logique au code que nous avons écrit ci-dessus. L'option est une entrée non essentielle qui peut être spécifiée. Dans cet exemple, ajoutez --greeting = [salutation] et --caps. La valeur par défaut de "Greet" est "Hello" ou "Goodbye", et l'utilisateur peut transmettre n'importe quelle valeur. Par exemple, si vous définissez --greeting = Wazzup, vous verrez Wazzup, [nom]. Si --caps est donné, l'affichage sera tout. Par exemple, «--caps» affichera «HELLO [NAME]».

Argparse

import argparse

#Depuis que j'ai commencé à vous saluer
#Fonction unifiée pour saluer
def greet(args):
    output = f"{args.greeting}, {args.name}"
    if args.caps:
        output = output.upper()
    print(output)

def main():
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    hello_parser = subparsers.add_parser("hello")
    #Ajouter un nom à l'argument
    hello_parser.add_argument("name")
    #Ajout d'une option de salutation et par défaut
    hello_parser.add_argument("--greeting", default="Hello")
    #Ajouter un indicateur avec False par défaut
    hello_parser.add_argument("--caps", action="store_true")
    hello_parser.set_defaults(func=greet)

    goodbye_parser = subparsers.add_parser("goodbye")
    goodbye_parser.add_argument("name")
    goodbye_parser.add_argument("--greeting", default="Goodbye")
    goodbye_parser.add_argument("--caps", action="store_true")
    goodbye_parser.set_defaults(func=greet)

    args = parser.parse_args()
    args.func(args)

if __name__ == "__main__":
    main()
$ python argparse/commands.py hello --greeting=Wazzup World
Wazzup, World

$ python argparse/commands.py hello --caps World
HELLO, WORLD

$ python argparse/commands.py hello --greeting=Wazzup --caps World
WAZZUP, WORLD

$ python argparse/commands.py hello --help
usage: commands.py hello \[-h\] [--greeting GREETING] [--caps] name

positional arguments:
    name

optional arguments:
    -h, --help           show this help message and exit
    --greeting GREETING
    --caps

Click

Ajoutez «salut» et «majuscules» avec «@ click.option». Puisqu'il y a une valeur par défaut, j'ai créé une fonction.

import click

def greeter(name, greeting, caps):
    output = f"{greeting}, {name}"
    if caps:
        output = output.upper()
    print(output)

@click.group()
def greet():
    pass

@greet.command()
@click.argument("name")
#Ajout d'une option de salutation et par défaut
@click.option("--greeting", default="Hello")
#Drapeau ajouté(is_flag=Peut être marqué avec True)
@click.option("--caps", is_flag=True)
def hello(name, greeting, caps):
    greeter(name, greeting, caps)

@greet.command()
@click.argument("name")
@click.option("--greeting", default="Goodbye")
@click.option("--caps", is_flag=True)
def goodbye(name, greeting, caps):
    greeter(name, greeting, caps)

if __name__ == "__main__":
    greet()
$ python click/commands.py hello --greeting=Wazzup World
Wazzup, World

$ python click/commands.py hello --caps World
HELLO, WORLD

$ python click/commands.py hello --greeting=Wazzup --caps World
WAZZUP, WORLD

$ python click/commands.py hello --helpUsage: commands.py hello [OPTIONS] NAME
Options:
    --greeting TEXT
    --caps
    --help           Show this message and exit.

Fire

Ajoutez des "salut" et des "majuscules" en ajoutant des arguments à la fonction. De plus, comme il existe un traitement commun, je l'ai récapitulé dans "greet".

import fire

def greet(name, greeting, caps):
    output = f"{greeting}, {name}"
    if caps:
        output = output.upper()
    print(output)

def hello(name, greeting="Hello", caps=False):
    greet(name, greeting, caps)

def goodbye(name, greeting="Goodbye", caps=False):
    greet(name, greeting, caps)

if __name__ == "__main__":
    fire.Fire({"hello": hello, "goodbye": goodbye})

Il y a une mise en garde à tirer lors du passage d'un bool. Le jeton après avoir passé --caps est passé à --caps. Il existe trois façons de le spécifier:

--Ajoutez l'option booléenne à la fin

$ python fire/commands.py hello --greeting=Wazzup World
Wazzup, World

$ python fire/commands.py hello --caps=True World
HELLO, WORLD

$ python fire/commands.py hello --greeting=Wazzup --caps=True World
WAZZUP, WORLD

$ python fire/commands.py hello --help
NAME
    commands.py hello

SYNOPSIS
    commands.py hello NAME <flags>

POSITIONAL ARGUMENTS
    NAME

FLAGS
    --greeting=GREETING
    --caps=CAPS

NOTES
    You can also use flags syntax for POSITIONAL ARGUMENTS
(END)

finalement

La plupart des choses que je fais sont fondamentalement petites, je vais donc utiliser Fire. Je pense à Click Next.

Page de référence

Comparing Python Command-Line Parsing Libraries – Argparse, Docopt, and Click

Recommended Posts

Comparaison des bibliothèques d'analyse de ligne de commande Python (argparse, click, fire)
[Python] Comment tester l'analyseur de ligne de commande cliquez sur
Traitement des arguments de ligne de commande (docopt Python)
Décomposer les arguments de commande en une seule ligne en Python
Créez une application de ligne de commande en Python pour comprendre les actions setup.py, argparse et GitHub
Modèle pour créer des applications de ligne de commande en Python
Comparaison approfondie de trois bibliothèques d'analyse morphologique Python
Mes réflexions sur le modèle d'application de ligne de commande python2.6
[Introduction à Udemy Python3 + Application] 67. Arguments de ligne de commande