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
python commands.py [command] [options] NAME
$ python commands.py hello World
Hello, World
$ python commands.py hellow World
Goodbye, World
$ 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.
Fonctionnalités supplémentaires (seront écrites plus tard)
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.
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 avec
set_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)
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 World --caps
--Passez les valeurs séparées par des espaces$ python fire/commands.py hello --caps True World
$ python fire/commands.py hello --caps=True World
$ 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)
Argparser
――Il a l'attrait d'être une bibliothèque standard, et il est bon à utiliser par contre, mais j'ai l'impression qu'elle ne convient pas pour créer une simple CLI.Click
―― J'aime les décorateurs parce que le code est petit et organisé pour faire des choses simples, mais quand je vais voir le code de noir
etc., il y a trop de décorateurs et la lisibilité est réduite, donc à petite échelle J'ai l'impression que cela convient.La plupart des choses que je fais sont fondamentalement petites, je vais donc utiliser Fire. Je pense à Click Next.
Comparing Python Command-Line Parsing Libraries – Argparse, Docopt, and Click
Recommended Posts