What's Cement
Framework d'application en ligne de commande python. ciment. Je n'ai pas beaucoup d'informations sur le japonais, alors faites une note pour moi-même sur Google plus tard.
Il dit "Un cadre, pour le CLI Ninja." Est-ce que toutes les choses cool sont ninja?
Vous pouvez l'installer avec pip.
pip install cement
Quelque chose comme ça. Si vous souhaitez créer un outil à fonction unique, ce niveau de modèle suffit.
myapp1 -h
myapp1 --option <option>
myapp1 --option -F <argument>
myapp1 --option -F <argument> <省略可能なargument>
myapp1 --option -F <argument> <省略可能なargument> <省略可能なargument> ....
Un contrôleur. Les options à définir individuellement sont «-F» et «--option». Un autre argument requis. Un nombre arbitraire d'arguments.
myapp.py
#-*- coding:utf-8 -*-
from cement.core.foundation import CementApp
from cement.core.controller import CementBaseController, expose
from cement.core import handler
class BaseController(CementBaseController):
class Meta:
label = 'base'
description = "Ceci est l'explication de cette commande"
arguments = [
( ['-o', '--option'],
dict(action='store', default="default option value",help='Je vais spécifier l'option') ),
( ['-F'],
dict(action='store_true', help='Option F supérieure') ),
(['param1'], dict(action='store', nargs=1, help = "C'est le premier argument")),
(['param2'], dict(action='store', nargs="*", metavar="PARAM2", help = "C'est le deuxième argument", default = ["default ext value"])),
]
@expose(hide=True)
def default(self):
self.app.log.debug("Traitement par défaut-début")
if self.app.pargs.option:
print "Les paramètres spécifiés par option sont<%s>" % self.app.pargs.option
if self.app.pargs.F:
print "L'option F a été spécifiée"
if self.app.pargs.param1:
print "argument: %s" % self.app.pargs.param1[0]
if self.app.pargs.param2:
print "argument: %s" % self.app.pargs.param2[0]
self.app.log.info("Traitement par défaut")
self.app.log.debug("Traitement par défaut-Fin")
class App(CementApp):
class Meta:
label = 'app'
base_controller = 'base'
handlers = [BaseController]
with App() as app:
app.run()
Le contrôleur interprète la méthode avec @exporse ()
comme une sous-commande. La méthode default
est appelée lorsque la sous-commande est omise.
@expose(aliases=["y!", "sb"], help="Description de la méthode par défaut")
def yahoo(self):
self.app.log.info("traitement Yahoo")
@expose(hide=True)
def default(self):
self.app.log.info("C'est le processus par défaut")
Les sous-commandes et les arguments de position sont difficiles à utiliser. Cela est dû au fait que les arguments et les paramètres d'option sont contrôlés par contrôleur, et si une sous-commande entre en collision avec un argument, elle sera interprétée comme une sous-commande. Par exemple, dans l'exemple ci-dessus, si vous omettez la sous-commande et passez default
ou yahoo
comme premier argument, cela ne fonctionnera pas. Elle sera interprétée comme une sous-commande.
Ceci est inévitable car il est inévitable lors de la conception d'une sous-commande de type CLI.
À propos, la définition de l'argument est commune dans le même contrôleur. Par conséquent, s'il existe un contrôleur qui a un argument requis, une sous-commande qui n'a pas d'argument ne peut pas y être définie.
Si vous voulez faire une telle conception, utilisez Namespace (contrôleur imbriqué) décrit plus loin.
Vous pouvez imbriquer les contrôleurs en tant qu'espace de noms. Example --Multiple Stacked Controllers est facile à comprendre.
Créez le système de commande suivant.
myapp2.py <argument>
myapp2.py sub
myapp2.py sub hello
myapp2.py sub world
Notez que l'appel simple à myapp2.py (c'est-à-dire MainController
) nécessite le premier argument, mais pas l'espace de noms sub
. «Hello» et «world» sont des sous-commandes de l'espace de noms «sub», pas des arguments.
myapp2.py
#-*- coding:utf-8 -*-
from cement.core.foundation import CementApp
from cement.core.controller import CementBaseController, expose
from cement.core import handler
class BaseController(CementBaseController):
class Meta:
label = 'base'
description = "C'est une explication de la commande de base."
class MainController(CementBaseController):
class Meta:
label = 'main'
description = "C'est une description du contrôleur principal"
stacked_on = 'base'
stacked_type = 'embedded'
arguments = [
(['param1'], dict(action='store', nargs=1, help="Premier argument requis"))
]
@expose(hide=True)
def default(self):
self.app.log.debug("Traitement par défaut-début")
print "argument: %s" % self.app.pargs.param1[0]
self.app.log.info("Traitement par défaut")
self.app.log.debug("Traitement par défaut-Fin")
class SubController(CementBaseController):
class Meta:
label = 'sub'
description = "C'est une description du sous-contrôleur"
stacked_on = 'base'
stacked_type = 'nested'
arguments = [ ]
@expose(hide=True)
def default(self):
self.app.log.info("Traitement du sous-contrôleur")
@expose()
def hello(self):
self.app.log.info("hello world")
@expose()
def world(self):
self.app.log.info("the world")
class App(CementApp):
class Meta:
label = 'app'
base_controller = 'base'
handlers = [BaseController, MainController, SubController]
with App() as app:
app.run()
Eh bien, cependant, du point de vue de l'utilisateur de la commande, sub
est une sous-commande.
Vous pouvez attribuer une valeur à app.exit_code.
@expose(hide=True)
def default(self):
self.app.log.error('Pas encore implémenté')
self.app.exit_code = 1
Sachez que la valeur de retour d'une sous-commande peut devenir par inadvertance la valeur de retour de la commande entière.
Faites-le fonctionner avec les spécifications de tuyau et de fichier.
cement3.py hello.txt
cat hello.txt | cement3.py
Vous pouvez écrire intelligemment en combinant ʻargparse.FileTypeet
default = sys.stdin`. Peut être un argument optionnel avec nargs = "?".
cement3.py
#-*- coding:utf-8 -*-
from cement.core.foundation import CementApp
from cement.core.controller import CementBaseController, expose
from cement.core import handler
import argparse
import sys
class BaseController(CementBaseController):
class Meta:
label = 'base'
description = "Ceci est l'explication de cette commande"
arguments = [
(["input"], dict(nargs='?', type=argparse.FileType('r'), default=sys.stdin ))
]
@expose(hide=True)
def default(self):
self.app.log.debug("Traitement par défaut-début")
for line in self.app.pargs.input:
print ">>> %s" % line
self.app.log.debug("Traitement par défaut-Fin")
class App(CementApp):
class Meta:
label = 'app'
base_controller = 'base'
handlers = [BaseController]
with App() as app:
app.run()
--Cement Le design est plutôt cool, alors utilisons-le et créons une CLI sympa.
Recommended Posts