Vorlage zum Schreiben von Batch-Skripten in Python

Da ich häufig Skripte für die Arbeit in Python schreibe, werde ich den Vorlagencode als Memorandum veröffentlichen.

Vorlage für die Python3-Serie

Überblick

Diese Vorlage führt Folgendes aus:

Dateipositionierung

app_home/
       ├ bin/
       │   └  my_batch.py   #← Skript zum Ausführen
       ├ conf/
       │   └  my_batch_conf.py #← Klasse einstellen
       ├ lib/
       │   ├  __init__.py    #← Erforderlich zum Laden des Moduls
       │   └  my_lib.py      #← Bibliothek
       ├ tests/        
       │   └  test_my_lib.py #← Unit-Testcode
       ├ log/                #← Ausgabeziel protokollieren
       └ Pipfile             #← Listen Sie die zu verwendenden Bibliotheken auf

Inhalt

Inhalt des Hauptteils my_batch.py

import sys
import os
import click
import logging

#Das übergeordnete Verzeichnis ist die Startseite der Anwendung(${app_home})Einstellen
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
# ${app_home}Zum Ladepfad der Bibliothek
sys.path.append(os.path.join(app_home))

#Laden Sie Ihre eigene Bibliothek
from lib.my_lib import MyLib

#Konfigurationsklasse laden
from conf.my_batch_conf import MyBatchConf

#Behandlung von Befehlszeilenargumenten. must_arg ist eine erforderliche Option, optional_arg ist optional
@click.command()
@click.option('--must_arg','-m',required=True)
@click.option('--optional_arg','-o',default="DefaultValue")
def cmd(must_arg,optional_arg):
    #Programmname ohne Erweiterung vom eigenen Namen(${prog_name})Zu
    prog_name = os.path.splitext(os.path.basename(__file__))[0]

    #Logger-Einstellungen

    #Format
    log_format = logging.Formatter("%(asctime)s [%(levelname)8s] %(message)s")
    #Niveau
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    #Handler zur Standardausgabe
    stdout_handler = logging.StreamHandler(sys.stdout)
    stdout_handler.setFormatter(log_format)
    logger.addHandler(stdout_handler)
    #Handler zum Protokollieren der Datei
    file_handler = logging.FileHandler(os.path.join(app_home,"log", prog_name + ".log"), "a+")
    file_handler.setFormatter(log_format)
    logger.addHandler(file_handler)

    #Starten Sie die Verarbeitung
    try:
        #Protokollausgabe
        logger.info("start")

        #Verwendung von Befehlszeilenargumenten
        logger.error(f"must_arg = {must_arg}")
        logger.error(f"optional_arg = {optional_arg}")

        #Bibliotheksaufruf
        mylib = MyLib()
        logger.info(mylib.get_name())

        #Verwendung von Sollwerten
        logger.info(MyBatchConf.key1)
        logger.info(MyBatchConf.key2)

        #Auch wenn eine Ausnahme auftritt ...
        raise Exception("My Exception")

    except Exception as e:
        #Ausnahmen abfangen und protokollieren
        logger.exception(e)
        sys.exit(1)

if __name__ == '__main__':
    cmd()        

Inhalt der Konfigurationsklasse conf / my_batch_conf.py

class MyBatchConf(object):
    key1 = "key1_value"
    key2 = True

*) Früher habe ich configParser verwendet, aber die config-Klasse muss nicht analysiert werden, und die IDE ergänzt sie, sodass ich sie nicht mehr verwende.

Inhalt der Bibliothek my_lib.py

class MyLib(object):
    def get_name(self):
        return "my_lib"

Inhalt des Testcodes der Bibliothekseinheit test_my_lib.py

import sys,os
import unittest

# ../Fügen Sie lib in den Ladepfad ein
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
sys.path.append(os.path.join(app_home,"lib"))

# ../Laden der zu testenden Bibliothek
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()

Lauf

Ohne Angabe eines Arguments ausführen

$ python bin/my_batch.py

Ausführungsergebnis (Handbuch erscheint durch Klickfunktion)

Usage: my_batch.py [OPTIONS]
Try "my_batch.py --help" for help.

Error: Missing option "--must_arg" / "-m".

Mit Argumenten ausführen

$ python bin/my_batch.py -m SpecifiedValue

Ausführungsergebnis

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

Der gleiche Inhalt wird in das Protokoll ausgegeben (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

Prüfung

Unit-Test ausführen

bash-3.2$ python tests/test_my_lib.py

Ausführungsergebnis

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Tests Der gesamte unten stehende Testcode test_ * .py wird sofort ausgeführt

$ python -m unittest  discover tests "test_*.py"

Schließlich

Dieser Code ist auch auf github → https://github.com/fetaro/python-batch-template-for-v3 verfügbar

Python2-Systemvorlage

Überblick

Diese Vorlage führt Folgendes aus:

Unterschied zur Python3-Serie

Dateipositionierung

app_home/
       ├ bin/
       │   └  my_batch.py   #← Skript zum Ausführen
       ├ conf/
       │   └  my_batch.conf #← Datei einstellen
       ├ lib/
       │   ├  __init__.py   #← Erforderlich zum Laden des Moduls
       │   └  my_lib.py     #← Bibliothek
       ├ tests/        
       │   └  test_my_lib.py#← Unit-Testcode
       └ log/               #← Ausgabeziel protokollieren

Inhalt

Inhalt von my_batch.py

# -*- coding: utf-8 -*-
import sys
import os
from optparse     import OptionParser
from ConfigParser import ConfigParser
import logging

#Das übergeordnete Verzeichnis ist die Startseite der Anwendung(${app_home})Einstellen
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))

# ${app_home}/Fügen Sie lib zum Ladepfad der Bibliothek hinzu
sys.path.append(os.path.join(app_home,"lib"))

#Laden Sie Ihre eigene Bibliothek
from my_lib import MyLib

if __name__ == "__main__" :
    #Programmname ohne Erweiterung vom eigenen Namen(${prog_name})Zu
    prog_name = os.path.splitext(os.path.basename(__file__))[0]

    #Optionale Perspektive
    usage = "usage: %prog (Argument-1) [options]"
    parser = OptionParser(usage=usage)
    parser.add_option("-d", "--debug",dest="debug", action="store_true", help="debug", default=False)

    #Speichern Sie Optionen und Argumente separat
    (options, args) = parser.parse_args()

    #Argumentprüfung
    if len(args) != 1:
        sys.stderr.write("argument error. use -h or --help option\n")
        sys.exit(1)

    #Lesen Sie die Konfigurationsdatei
    config = ConfigParser()
    conf_path = os.path.join(app_home,"conf", prog_name + ".conf")
    config.read(conf_path)

    #Logger-Einstellungen

    #Format
    log_format = logging.Formatter("%(asctime)s [%(levelname)8s] %(message)s") 
    #Niveau
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    #Handler zur Standardausgabe
    stdout_handler = logging.StreamHandler(sys.stdout)
    stdout_handler.setFormatter(log_format)
    logger.addHandler(stdout_handler)
    #Handler zum Protokollieren der Datei
    file_handler = logging.FileHandler(os.path.join(app_home,"log", prog_name + ".log"), "a+")
    file_handler.setFormatter(log_format)
    logger.addHandler(file_handler)

    
    #Starten Sie die Verarbeitung
    try:
        #Protokollausgabe
        logger.info("start")
        logger.error("arg1 = {0}".format(args[0]))

        #Optionen abrufen
        logger.info(options.debug)

        #Bibliotheksaufruf
        mylib = MyLib()
        logger.info(mylib.get_name())

        #Einstellwert lesen
        logger.info(config.get("section1","key1"))
        logger.info(config.getboolean("section2","key2"))

        #Auch wenn eine Ausnahme auftritt ...
        raise Exception("My Exception")
        
    except Exception as e:
        #Ausnahmen abfangen und protokollieren
        logger.exception(e)
        sys.exit(1)
        

Inhalt von my_batch.conf

[section1]
key1  = key1_value

[section2]
key2 = true

Inhalt von my_lib.py

class MyLib(object):
    def get_name(self):
        return "my_lib"

Inhalt des Unit-Test-Codes test_my_lib.py

# -*- coding: utf-8 -*-
import sys,os
import unittest

# ../Fügen Sie lib in den Ladepfad ein
app_home = os.path.abspath(os.path.join( os.path.dirname(os.path.abspath(__file__)) , ".." ))
sys.path.append(os.path.join(app_home,"lib"))

# ../Laden der zu testenden Bibliothek
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()

Lauf

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

Inhalt des Protokolls (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

Ergebnis der Unit-Test-Ausführung

bash-3.2$ python tests/test_my_lib.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Tests Beim gleichzeitigen Testen aller Testcodes test_ *. Py unter den folgenden Bedingungen

bash-3.2$ python -m unittest  discover tests "test_*.py"

Der Inhalt dieser Datei wird auch auf github veröffentlicht. Bitte machen Sie, was Sie wollen → https://github.com/fetaro/python-batch-template

Recommended Posts

Vorlage zum Schreiben von Batch-Skripten in Python
Techniken zum Sortieren in Python
Python-Vorlage für Codeforces-manuelle Test-
Einrückungsformatierung von Python-Skripten
Über "für _ in range ():" von Python
Suchen Sie mit Python nach externen Befehlen
Minimale Grammatiknotizen zum Schreiben von Python
Vorverarbeitungsvorlage für die Datenanalyse (Python)
Führen Sie unittest in Python aus (für Anfänger)
Lesen und Schreiben von Text in Python
Beim Schreiben eines Programms in Python
Anmerkung von nfc.ContactlessFrontend () von nfcpy von Python
Inject wird für DDD in Python empfohlen
Tipps zum Umgang mit Binärdateien in Python
Zusammenfassung verschiedener for-Anweisungen in Python
Geben Sie Anmerkungen für Python2 in Stub-Dateien ein!
Treiberskript zur parametrischen Berechnung von Python-Skripten
Ich kann Python-Skripte in Eclipse nicht debuggen
Verarbeiten Sie mehrere Listen mit for in Python
MongoDB mit Python zum ersten Mal
Holen Sie sich ein Zeichen für Conoha mit Python
Beispiel für den Umgang mit EML-Dateien in Python
AtCoder Spickzettel in Python (für mich)
Ich habe mit Python nach einer Primzahl gesucht
Hinweise zur Verwendung von Python (Pydev) mit Eclipse
Tipps zum Erstellen kleiner Werkzeuge mit Python
Verwenden Sie pathlib in Maya (Python2.7), um sich auf das kommende Python3.7 vorzubereiten
2016-10-30 sonst für Python3> für:
[Tipps] Leicht lesbares Schreiben beim Verbinden von Funktionen in Python
Quadtree in Python --2
Python [für mich]
CURL in Python
CERTIFICATE_VERIFY_FAILED in Python 3.6, dem offiziellen Installationsprogramm für macOS
Metaprogrammierung mit Python
Python 3.3 mit Anaconda
Geokodierung in Python
SendKeys in Python
Python-Vorlage, die eine Protokollanalyse mit explosiver Geschwindigkeit durchführt
Python Pandas ist nicht für die Stapelverarbeitung geeignet
Metaanalyse in Python
Unittest in Python
Erstellen einer Umgebung zum Ausführen von Python-Skripten (für Mac)
Lernen Sie das Entwurfsmuster "Vorlagenmethode" in Python
Zwietracht in Python
Fügen Sie ein Zitat ">" für die Beantwortung von E-Mails in Python3 hinzu
DCI in Python
Quicksort in Python
nCr in Python
Protokollierungseinstellungen für die tägliche Protokollrotation mit Python
Lesen und Schreiben von CSV- und JSON-Dateien mit Python
Python-Grundschrift
Tipps zum Erreichen der ATND-API mit Python
Zeigen Sie FX (Forex) Daten Candle Stick in Python an
N-Gramm in Python
Programmieren mit Python
Boost.NumPy Tutorial zum Erweitern von Python in C ++ (Übung)
Füllen Sie dynamische Variablenwerte in Python mit 0