Comme j'écris souvent des scripts en Python pour le travail, je publierai le code du modèle sous forme de mémorandum.
Ce modèle effectue les opérations suivantes:
app_home/
├ bin/
│ └ my_batch.py #← Script à exécuter
├ conf/
│ └ my_batch_conf.py #← Classe de réglage
├ lib/
│ ├ __init__.py #← Nécessaire pour charger le module
│ └ my_lib.py #← Bibliothèque
├ tests/
│ └ test_my_lib.py #← Code de test unitaire
├ log/ #← Destination de sortie du journal
└ Pipfile #← Lister les bibliothèques à utiliser
Contenu du corps principal my_batch.py
import sys
import os
import click
import logging
#Le répertoire parent est le siège de l'application(${app_home})Mis à
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
# ${app_home}Vers le chemin de chargement de la bibliothèque
sys.path.append(os.path.join(app_home))
#Chargez votre propre bibliothèque
from lib.my_lib import MyLib
#Charger la classe de configuration
from conf.my_batch_conf import MyBatchConf
#Gestion des arguments de ligne de commande. must_arg est une option obligatoire, facultative_arg est facultatif
@click.command()
@click.option('--must_arg','-m',required=True)
@click.option('--optional_arg','-o',default="DefaultValue")
def cmd(must_arg,optional_arg):
#Nom du programme sans extension de son propre nom(${prog_name})À
prog_name = os.path.splitext(os.path.basename(__file__))[0]
#Paramètres de l'enregistreur
#format
log_format = logging.Formatter("%(asctime)s [%(levelname)8s] %(message)s")
#niveau
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#Gestionnaire vers la sortie standard
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setFormatter(log_format)
logger.addHandler(stdout_handler)
#Gestionnaire vers fichier journal
file_handler = logging.FileHandler(os.path.join(app_home,"log", prog_name + ".log"), "a+")
file_handler.setFormatter(log_format)
logger.addHandler(file_handler)
#Commencer le traitement
try:
#Sortie de journal
logger.info("start")
#Utilisation d'arguments de ligne de commande
logger.error(f"must_arg = {must_arg}")
logger.error(f"optional_arg = {optional_arg}")
#Appel à la bibliothèque
mylib = MyLib()
logger.info(mylib.get_name())
#Utilisation des valeurs de consigne
logger.info(MyBatchConf.key1)
logger.info(MyBatchConf.key2)
#Même si une exception se produit ...
raise Exception("My Exception")
except Exception as e:
#Attraper et enregistrer les exceptions
logger.exception(e)
sys.exit(1)
if __name__ == '__main__':
cmd()
Contenu de la classe de configuration conf / my_batch_conf.py
class MyBatchConf(object):
key1 = "key1_value"
key2 = True
*) J'avais l'habitude d'utiliser configParser avant, mais je n'ai pas besoin de l'analyser dans la classe de configuration, et je ne l'utilise pas maintenant car la complétion par IDE fonctionne.
Contenu de la bibliothèque my_lib.py
class MyLib(object):
def get_name(self):
return "my_lib"
Contenu du code de test unitaire de la bibliothèque test_my_lib.py
import sys,os
import unittest
# ../Mettez lib dans le chemin de chargement
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
sys.path.append(os.path.join(app_home,"lib"))
# ../Chargement de la bibliothèque en cours de test
from my_lib import MyLib
class TestMyLib(unittest.TestCase):
def test_get_name(self):
ml = MyLib()
self.assertEqual("my_lib", ml.get_name())
if __name__ == '__main__':
unittest.main()
Exécuter sans spécifier d'argument
$ python bin/my_batch.py
Résultat de l'exécution (le manuel apparaît par fonction clic)
Usage: my_batch.py [OPTIONS]
Try "my_batch.py --help" for help.
Error: Missing option "--must_arg" / "-m".
Exécuter avec des arguments
$ python bin/my_batch.py -m SpecifiedValue
Résultat d'exécution
2019-06-28 16:42:53,335 [ INFO] start
2019-06-28 16:42:53,335 [ ERROR] must_arg = SpecifiedValue
2019-06-28 16:42:53,335 [ ERROR] optional_arg = DefaultValue
2019-06-28 16:42:53,335 [ INFO] my_lib
2019-06-28 16:42:53,336 [ INFO] key1_value
2019-06-28 16:42:53,336 [ INFO] True
2019-06-28 16:42:53,336 [ ERROR] My Exception
Traceback (most recent call last):
File "bin/my_batch.py", line 62, in cmd
raise Exception("My Exception")
Exception: My Exception
Le même contenu est sorti dans le journal (log / my_batch.log)
2019-06-28 16:42:53,335 [ INFO] start
2019-06-28 16:42:53,335 [ ERROR] must_arg = SpecifiedValue
2019-06-28 16:42:53,335 [ ERROR] optional_arg = DefaultValue
2019-06-28 16:42:53,335 [ INFO] my_lib
2019-06-28 16:42:53,336 [ INFO] key1_value
2019-06-28 16:42:53,336 [ INFO] True
2019-06-28 16:42:53,336 [ ERROR] My Exception
Traceback (most recent call last):
File "bin/my_batch.py", line 62, in cmd
raise Exception("My Exception")
Exception: My Exception
Exécuter un test unitaire
bash-3.2$ python tests/test_my_lib.py
Résultat d'exécution
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
tests Tout le code de test test_ * .py
ci-dessous est exécuté en une
$ python -m unittest discover tests "test_*.py"
Ce code est également disponible sur github → https://github.com/fetaro/python-batch-template-for-v3
Ce modèle effectue les opérations suivantes:
Différence par rapport à la série python3
# - * - coding: utf-8 - * -
est requise au début du fichier (car le code source est en japonais).format ()
au lieu de l'expression f pour formater la chaîneapp_home/
├ bin/
│ └ my_batch.py #← Script à exécuter
├ conf/
│ └ my_batch.conf #← Fichier de configuration
├ lib/
│ ├ __init__.py #← Nécessaire pour charger le module
│ └ my_lib.py #← Bibliothèque
├ tests/
│ └ test_my_lib.py#← Code de test unitaire
└ log/ #← Destination de sortie du journal
Contenu de my_batch.py
# -*- coding: utf-8 -*-
import sys
import os
from optparse import OptionParser
from ConfigParser import ConfigParser
import logging
#Le répertoire parent est le siège de l'application(${app_home})Mis à
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
# ${app_home}/Ajouter une bibliothèque au chemin de chargement de la bibliothèque
sys.path.append(os.path.join(app_home,"lib"))
#Chargez votre propre bibliothèque
from my_lib import MyLib
if __name__ == "__main__" :
#Nom du programme sans extension de son propre nom(${prog_name})À
prog_name = os.path.splitext(os.path.basename(__file__))[0]
#Perspective facultative
usage = "usage: %prog (Argument-1) [options]"
parser = OptionParser(usage=usage)
parser.add_option("-d", "--debug",dest="debug", action="store_true", help="debug", default=False)
#Stocker les options et les arguments séparément
(options, args) = parser.parse_args()
#Vérification des arguments
if len(args) != 1:
sys.stderr.write("argument error. use -h or --help option\n")
sys.exit(1)
#Lire le fichier de configuration
config = ConfigParser()
conf_path = os.path.join(app_home,"conf", prog_name + ".conf")
config.read(conf_path)
#Paramètres de l'enregistreur
#format
log_format = logging.Formatter("%(asctime)s [%(levelname)8s] %(message)s")
#niveau
logger = logging.getLogger()
logger.setLevel(logging.INFO)
#Gestionnaire vers la sortie standard
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setFormatter(log_format)
logger.addHandler(stdout_handler)
#Gestionnaire vers fichier journal
file_handler = logging.FileHandler(os.path.join(app_home,"log", prog_name + ".log"), "a+")
file_handler.setFormatter(log_format)
logger.addHandler(file_handler)
#Commencer le traitement
try:
#Sortie de journal
logger.info("start")
logger.error("arg1 = {0}".format(args[0]))
#Obtenez des options
logger.info(options.debug)
#Appel à la bibliothèque
mylib = MyLib()
logger.info(mylib.get_name())
#Lire la valeur de réglage
logger.info(config.get("section1","key1"))
logger.info(config.getboolean("section2","key2"))
#Même si une exception se produit ...
raise Exception("My Exception")
except Exception as e:
#Attraper et enregistrer les exceptions
logger.exception(e)
sys.exit(1)
Contenu de my_batch.conf
[section1]
key1 = key1_value
[section2]
key2 = true
Contenu de my_lib.py
class MyLib(object):
def get_name(self):
return "my_lib"
Contenu du code de test unitaire test_my_lib.py
# -*- coding: utf-8 -*-
import sys,os
import unittest
# ../Mettez lib dans le chemin de chargement
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
sys.path.append(os.path.join(app_home,"lib"))
# ../Chargement de la bibliothèque en cours de test
from my_lib import MyLib
class TestMyLib(unittest.TestCase):
def test_get_name(self):
ml = MyLib()
self.assertEqual("my_lib", ml.get_name())
if __name__ == '__main__':
unittest.main()
bash-3.2$ python bin/my_batch.py argument1
2016-08-16 23:25:03,492 [ INFO] start
2016-08-16 23:25:03,492 [ ERROR] arg1 = argument1
2016-08-16 23:25:03,492 [ INFO] False
2016-08-16 23:25:03,492 [ INFO] my_lib
2016-08-16 23:25:03,492 [ INFO] key1_value
2016-08-16 23:25:03,492 [ INFO] True
2016-08-16 23:25:03,492 [ ERROR] My Exception
Traceback (most recent call last):
File "bin/my_batch.py", line 73, in <module>
raise Exception("My Exception")
Exception: My Exception
Contenu du journal (log / my_batch.log)
2016-08-16 23:25:03,492 [ INFO] start
2016-08-16 23:25:03,492 [ ERROR] arg1 = argument1
2016-08-16 23:25:03,492 [ INFO] False
2016-08-16 23:25:03,492 [ INFO] my_lib
2016-08-16 23:25:03,492 [ INFO] key1_value
2016-08-16 23:25:03,492 [ INFO] True
2016-08-16 23:25:03,492 [ ERROR] My Exception
Traceback (most recent call last):
File "bin/my_batch.py", line 73, in <module>
raise Exception("My Exception")
Exception: My Exception
Résultat de l'exécution du test unitaire
bash-3.2$ python tests/test_my_lib.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
tests Lors du test de tout le code de test test_ *. Py
sous ce qui suit à la fois
bash-3.2$ python -m unittest discover tests "test_*.py"
Le contenu de ce fichier est également publié sur github. Faites ce que vous voulez → https://github.com/fetaro/python-batch-template
Recommended Posts