Modèle pour créer des applications de ligne de commande en Python

Comment créer une application de ligne de commande en Python

Lors de la création d'une application de ligne de commande en Python (telle que python httpie) Écrire ** entry_point ** dans setup.py est le courant dominant, n'est-ce pas?

setup.py


from setuptools import setup

setup(
    # ...Omission...
    entry_points={
        "console_scripts": [
            "my-console-app=my_console_app.__main__:main"
        ]
    },
    # ...Omission...
)

Dans le cas ci-dessus, la fonction main écrite en __main __. Py du package my_console_app est définie comme une application appelée my-console-app.

Et l'important est de savoir comment écrire cette ** fonction principale **. Dans cet article, je vais vous présenter le modèle de la fonction principale qui s'est établie lors de la création d'applications console.

Quoi écrire dans la fonction principale

Tout ce dont vous avez besoin pour la fonction principale

Je pense.

Obtenir des arguments de ligne de commande à l'aide d'argparse

Les applications de ligne de commande acceptent généralement des arguments. Par exemple, dans le cas de httpie mentionné dans l'exemple,

$ http PUT http://httpbin.org/put hello=world

Prenez un argument comme celui-ci. (PUT, http: // httpbin.org / put, hello = world sont tous des arguments) Il existe une bibliothèque standard appelée ** argparse ** pour définir et obtenir des arguments de ligne de commande en Python.

from argparse import ArgumentParser

parser = ArgumentParser(
    prog="my-console-app",
    description="This is my console application.")

parser.add_argument(
    "message",
    action="store",
    help="The message string.")

Définissez des arguments de ligne de commande comme celui-ci. N'écrivez pas sur argparse en détail car cela rendra l'article inutilement long. Veuillez vérifier par vous-même.

La fonction main utilise l'analyseur créé par cette argpase pour obtenir des arguments de ligne de commande.

__main__.py



from .cli import parser #Cli à l'intérieur du paquet.Définir l'analyseur dans le fichier py

def main(argv=sys.argv):
    
    args = parser.parse_args()

Implémentation interne de l'application

Ensuite, vous devez implémenter l'application elle-même. Cette application utilise les arguments de ligne de commande obtenus ci-dessus pour modifier le contenu de sortie, donc

__main__.py



from .cli import parser
from .core import program #Noyau à l'intérieur du paquet.Implémenter l'application dans py

def main(argv=sys.argv):

    args = parser.parse_args()
    program(args) #Étant donné que les arguments de ligne de commande sont nécessaires pour exécuter l'application, prenez args comme argument

De cette façon, il est bon de prendre l'argument de ligne de commande après l'analyse comme argument du programme.

Définition du statut de résiliation

Quel est l'état de sortie? L'état de sortie (anglais: état de sortie) ou code retour (anglais: code retour) d'un processus en programmation informatique est une procédure ou une tâche spécifique à laquelle un processus enfant (ou appelé) est délégué. Est un petit nombre à transmettre au processus parent (ou à l'appelant) une fois l'exécution terminée. [End Status-wikipedia](https://ja.wikipedia.org/wiki/%E7%B5%82%E4%BA%86%E3%82%B9%E3%83%86%E3%83%BC% E3% 82% BF% E3% 82% B9)

En savoir plus sur le statut de sortie vous-même. Quoi qu'il en soit, lorsque l'application se ferme, c'est ** un entier pour déterminer si l'application s'est terminée correctement ou si elle s'est terminée anormalement avec une erreur **. Incorporons cela dans la fonction principale.

Concernant cet état de fin, il est préférable de l'implémenter pour que le programme à l'intérieur de l'application renvoie l'état de fin plutôt que de le définir dans la fonction principale. Qu'est-ce que ça veut dire?

__main__.py



import sys
from .cli import parser
from .core import program

def main(argv=sys.argv):

    args = parser.parse_args()
    exit_status = program(args) #Il est bon de mettre en œuvre pour que le programme à l'intérieur de l'application renvoie l'état de fin
    
    return sys.exit(exit_status)

Voilà ce que c'est.

Sortie d'erreur

Puisqu'il s'agit d'une application qui s'exécute sur une console, il est plus facile pour les utilisateurs de générer correctement les erreurs.

$ my-console-app -m 1111
Traceback (most recent call last):                                                                                                                            
  File "/home/vagrant/.anyenv/envs/pyenv/versions/2.7.5/lib/python2.7/runpy.py", line 162, in _run_module_as_main                                             
    "__main__", fname, loader, pkg_name)                                                                        
  File "/home/vagrant/.anyenv/envs/pyenv/versions/2.7.5/lib/python2.7/runpy.py", line 72, in _run_code                                                        
    exec code in run_globals                                                                                                                                  
  File "/home/vagrant/lab/Python/my-console-app/my_console_app/__main__.py", line 63, in <module>                                                              
    main()                                                                                                                                                    
  File "/home/vagrant/lab/Python/my-console-app/my_console_app/__main__.py", line 52, in main                                                                   
    exit_code = program(args)                                                                                                                                 
  File "/home/vagrant/lab/Python/my-console-app/my_console_app/__main__.py", line 34, in program                                                               
    print prettyprint(result)                                                                                                                                 
  File "my_console_app/utils.py", line 50, in prettyprint                                                                                                          
    raise TypeError("Message must be string not integer")
TypeError: Message must be string not integer                          

** La seule erreur que je veux signaler est la dernière phrase **, mais quand autant d'informations sortent, les utilisateurs qui ne font rien auront peur. Par conséquent, ce format d'erreur doit être affiché uniquement pour la dernière phrase.

__main__.py



import sys
from .cli import parser
from .core import program

def main(argv=sys.argv):

    args = parser.parse_args()

    try:
        exit_status = program(args) #Il est bon de mettre en œuvre pour que le programme à l'intérieur de l'application renvoie l'état de fin
        return sys.exit(exit_status)

    except Exception as e:
        error_type = type(e).__name__ # 29.6.2 Addendum: vous pouvez obtenir le nom de l'erreur avec ce
        sys.stderr.write("{0}: {1}\n".format(error_type, e.message))
        sys.exit(1) #Si l'état de fin est un entier différent de 0, cela indique une fin anormale.

Si vous écrivez un code comme celui-ci, l'erreur sera générée comme suit.

$ my-console-app -m 1111
TYpeError: Message must be string not integer    

C'est plus facile à voir! !!

Mais si vous pensez que vous ne pouvez pas voir les détails de l'erreur dans l'application. Il existe une solution de contournement.

  1. Ajoutez l'argument ** --stack-trace ** à l'analyseur créé par argparse
  2. Sortie de la trace de pile en utilisant la bibliothèque ** traceback ** s'il y a un argument --stack-trace lorsqu'une erreur se produit

cli.py


parser.add_argument(
    "--stack-trace",
    dest="stacktrace",
    action="store_true",
    help="Display the stack trace when error occured.")

__main__.py



import sys
import traceback
from .cli import parser
from .core import program

def main(argv=sys.argv):

    if len(argv) == 1:
        # 2017.04.29 Correction
        # len(argv) ==C'était 1 au lieu de 0. Excusez-moi
        parser.parse_args(["-h"])

    args = parser.parse_args(argv)

    try:
        exit_code = program(args)
        sys.exit(exit_code)

    except Exception as e:
        error_type = type(e).__name__ # 29.6.2 Addendum: vous pouvez obtenir le nom de l'erreur avec ce
        stack_trace = traceback.format_exc() #Enregistrer la trace de la pile lorsqu'une erreur se produit

        if args.stacktrace: # --stack-Trace de la pile de sortie s'il y a un argument de trace
            print "{:=^30}".format(" STACK TRACE ")
            print stack_trace.strip()

        else:
            sys.stderr.write(
                "{0}: {1}\n".format(e_type, e.message))
            sys.exit(1)

Modèle pour créer des applications de ligne de commande en Python

En d'autres termes, le modèle de la fonction principale est le suivant.

__main__.py



import sys
import traceback
from .cli import parser
from .core import program

def main(argv=sys.argv):

    if len(argv) == 1:
        # 2017.04.29 Correction
        # len(argv) ==C'était 1 au lieu de 0. Excusez-moi

        parser.parse_args(["-h"]) #Afficher un message d'aide s'il n'y a pas d'arguments de ligne de commande
        sys.exit(0)

    args = parser.parse_args(argv)

    try:
        exit_code = program(args)
        sys.exit(exit_code)

    except Exception as e:
         error_type = type(e).__name__ # 29.6.2 Addendum: vous pouvez obtenir le nom de l'erreur avec ce
         stack_trace = traceback.format_exc()

        if args.stacktrace:
            print "{:=^30}".format(" STACK TRACE ")
            print stack_trace.strip()

        else:
            sys.stderr.write(
                "{0}: {1}\n".format(e_type, e.message))
            sys.exit(1)

2017.04.29 Correction

Du code ci-dessus


if len(sys.argv) == 0:
    parser.parse_args(["-h"])

Il y a eu une erreur dans cette partie. Correctement


if len(sys.argv) == 1: # 0 -> 1
    parser.parse_args(["-h"])

Le but de ce code (pour obtenir un message d'aide de l'analyseur) est que dans le cas d'argparse, si vous démarrez l'application sans définir d'arguments de ligne de commande,

usage: setup-script [-h] [-l] [--stack-trace] formula project
setup-script: error: too few arguments

Puisqu'un tel message d'erreur (signifiant qu'il n'y a pas d'argument) est affiché, si sys.argv vaut 1 avec l'intention de ne pas émettre cette erreur,parser.parse_args (["-h"]) Le message d'aide est émis sous la forme.

2017.6.2 Addendum

J'ai appris que vous pouvez utiliser type (e) .__ name__ pour obtenir le nom de l'erreur à partir de l'objet d'erreur.

Recommended Posts

Modèle pour créer des applications de ligne de commande en Python
Modèle pour l'écriture de scripts batch en python
Décomposer les arguments de commande en une seule ligne en Python
Comment recevoir des arguments de ligne de commande en Python
Mes réflexions sur le modèle d'application de ligne de commande python2.6
Bonnes pratiques personnelles pour placer un projet Python de lancement en ligne de commande dans un conteneur Docker
[Pour les débutants] Comment utiliser la commande say avec python!
Spécifiez une sous-commande comme argument de ligne de commande en Python
Une collection de lignes de commande qui utilisent des environnements virtuels avec Anaconda
Fizzbuzz en Python (en une ligne)
Exécuter des commandes externes avec python
Techniques de tri en Python
Essayez LINE Notify avec Python
Modèle Python pour Codeforces-test manuel-
Exécution de commandes externes en Python
À propos de "for _ in range ():" de python
Autoriser l'installation des outils de ligne de commande en Python
Google recherche la chaîne sur la dernière ligne du fichier en Python
Rechercher les fuites de mémoire dans Python
Traitement des arguments de ligne de commande (docopt Python)
Segfo python en une ligne
Rechercher des commandes externes avec python
Appuyez sur une commande en Python (Windows)
Outil de ligne de commande Chainer ChainerCMD
Exécutez la commande shell / Python dans R
Dans la commande python, python pointe vers python3.8
Image de conteneur recommandée pour les applications Python
Modèle de prétraitement pour l'analyse des données (Python)
Exécutez unittest en Python (pour les débutants)
J'ai essayé la notification de ligne en Python
[Introduction] Insérer des sauts de ligne dans Python 3
Implémenté en 1 minute! LINE Notify en Python
Commande pour le répertoire courant Python
python Remarque: déterminez si l'argument de ligne de commande est dans la liste
Comment obtenir une chaîne à partir d'un argument de ligne de commande en python
CGI Server (1) édition python en une ligne
[LLDB] Créez votre propre commande avec Python
Note de nfc.ContactlessFrontend () de nfcpy de python
Inject est recommandé pour DDD en Python
Graphique à lignes pliées et ligne d'échelle en python
Apprenez le modèle de conception "Commande" en Python
Conseils pour gérer les binaires en Python
Le paramètre d'environnement Python amateur (pour MAC) est en cours de création
Résumé de diverses instructions for en Python
Tapez les annotations pour Python2 dans les fichiers stub!
Lisez le fichier ligne par ligne avec Python
Traiter plusieurs listes avec for en Python
Lisez le fichier ligne par ligne avec Python
Obtenez des options en Python à partir des fichiers JSON et des arguments de ligne de commande
MongoDB avec Python pour la première fois
Obtenez un jeton pour conoha avec python
Exemple de gestion des fichiers eml en Python
Conseils pour créer de grandes applications avec Flask
Fiche de triche AtCoder en python (pour moi-même)
J'ai cherché un nombre premier avec python
Remarques sur l'utilisation de python (pydev) avec eclipse
Conseils pour créer de petits outils avec python
[Python] Inversion de valeur booléenne en une ligne
Utilisez pathlib dans Maya (Python2.7) en préparation du prochain Python3.7
Notes J'ai recherché la création d'outils de ligne de commande en Python