Erfahren Sie mehr über die Protokollierung mit dem Python-Protokollierungsmodul ①

Einführung

Ich bin sicher, dass viele Leute dies getan haben, indem sie einen Loggernamen angegeben und eine Loggerinstanz verwendet haben (wie getLogger (__ name __) in Python). Ich denke, es gibt viele Leute, die nur an diesen Loggernamen und den zu protokollierenden Namen denken. Also habe ich versucht zu lernen, wie man mit Easy Python eine gemeinsame Protokollierungsbibliothek erstellt.

Bedenken

Hier ist eine kurze Zusammenfassung Ihrer Bedenken bei der Protokollierung. Beachten Sie, dass diese nicht notwendig und ausreichend sind und dass dieser Artikel nicht für alle eine Lösung bietet.

――Wie verwenden Sie den Namen, den Sie bei der Verwendung von Logger festgelegt haben?

Annahme

Dieser Artikel ist für Python und Flask gedacht, mit denen ich häufig Validierungscode implementiere. Auf der anderen Seite sind die oben genannten Bedenken für Sprachen und Betriebssysteme (die häufig wie Linux verwendet werden) gleich. Mit anderen Worten, das Wissen darüber, wie sich die diesmal ausgewählte Sprache und das ausgewählte Framework nähern / worauf sich der Programmierer bei der Verwendung dieser konzentrieren sollte, kann auch bei der Verwendung anderer Sprachen und Frameworks verwendet werden. Ich denke es könnte sein.

Fangen Sie an zu lernen

Die Einführung ist länger geworden.

Logger-Instanz und Logger-Baum

Informationen zur Logger-Instanz

Um die Protokollierungsbibliothek zu verstehen, müssen wir zunächst die Logger-Instanz kennen.

Wenn Sie Protokolle mit dem Protokollierungspaket schreiben, bitten wir die Logger-Instanz, den Job auszuführen. Logger-Instanzen sind die ** einzige Instanz **, die für bestimmte Protokollierungsaktivitäten verantwortlich ist. Eine gute Möglichkeit für Programmierer, eine Logger-Instanz in ihrem Code zu verwenden, besteht darin, eine an das Protokollierungsmodul angehängte Protokollierungsfunktion aufzurufen (z. B. "logging.warning ()") oder eine Logger-Instanz mit "getLogger (name = None)" abzurufen. Ist diese Protokollierungsmethode aufzurufen. (Es ist keine neue Instanz aus der Logger-Klasse!)

Wie Sie beim Lesen des Protokollierungsmoduls sehen können, ruft jede Protokollierungsfunktion im Protokollierungsmodul selbst die [Root-Logger-Instanzmethode] auf. Ich bin](https://github.com/python/cpython/blob/3.8/Lib/logging/init.py#L2047). Der Root-Logger wird beim Laden des Logging-Moduls generiert und im Bereich des Moduls gehalten.

Wie man es benutzt ist so.

use_root_logger.py


import logging

# https://docs.python.org/ja/3/library/logging.html
# https://docs.python.org/ja/3/howto/logging.html
logging.warning('Watch out!')  # will print a message to the console
logging.info('I told you so')  # will not print anything

Als nächstes über die Logger-Instanz. Es gibt nur eine Logger-Instanz im selben Prozess, die von getLogger (name = None) abgerufen werden kann. Mit anderen Worten, es ist Singleton. Jede Logger-Instanz wird von "logging.Manager" verwaltet, und "logging.Manager" selbst wird [instanziiert](https: /), sodass sie beim Laden des Protokollierungsmoduls zu einem Klassenfeld der Klasse "logging.Logger" wird. /github.com/python/cpython/blob/3.8/Lib/logging/init.py#L1890). logging.Manager sucht nach einer vorhandenen Logger-Instanz mit dem Argumentnamen als Schlüssel und gibt diese Instanz zurück, falls vorhanden.

Sie müssen nicht lange nachdenken, und so verwenden Sie es.

use_get_logger.py


import logging

# https://docs.python.org/ja/3/library/logging.html
# https://docs.python.org/ja/3/howto/logging.html
logger = logging.getLogger('simple_example')
#Unterlassung
logger.warning('warn message')

Logger-Baum

Das Wort Root Logger kam heraus. In vielen Protokollierungsbibliotheken ist Logger ein Singleton und hat eine Baumstruktur. (Zumindest weiß ich, dass Python-Protokollierung, java java.util.logging, org.apache.logging.log4j. C # NLog war sicherlich das gleiche.)

Der Logger im Protokollierungsmodul hat eine Baumstruktur mit dem Root-Logger als Apex. Es ist möglicherweise leichter vorstellbar, dass es sich um eine Verzeichnisstruktur für Personen im Internetbereich und Windows-Infrastrukturingenieure wie mich handelt. Es mag viele Zwecke für dieses Design geben, aber ich denke, der größte Vorteil ist, dass die Namespaces getrennt werden können und die einzige Ressource klar dargestellt werden kann. Da logging.Manager Logger-Instanzen anhand von Zeichenfolgen identifiziert und verwaltet, ist es einfach, die Eindeutigkeit der Ressource namens Logger-Instanz beizubehalten, da die Methode zum Erstellen einer Baumstruktur wie FQDN tot ist.

Angenommen, Sie haben einen Support-Service für Reisende in Shimoro Onsen eingerichtet. Das Reservierungssystem hat die Subsystem-ID "Buch", das Reservierungs-Web hat "Web", die API hat "API", OSS wird als Entwicklungsframework verwendet und die Protokolle werden getrennt, da sie von verschiedenen Teams betrieben werden. Wenn dies der Fall ist, ist es zweckmäßig, die Logger-Instanz durch diese Einheit zu teilen. So was.

gero_onsen.py


web_book_logger = logging.getLogger('gero.book.web')
... #Legen Sie einen Handler fest, der in die Datenbank eingefügt werden soll, die auf dem Verwaltungsbenutzerbildschirm angezeigt wird

api_book_logger = logging.getLogger('gero.book.api')
... #Stellen Sie die Handler so ein, dass sie zu CloudWatch-Protokollen fliegen

from flask import Flask
app = Flask('gero')
app.logger.addHandler(...) #Richten Sie einen Handler ein, um das Infrastruktur-Team über Slack zu benachrichtigen

Da die Loggernamen durch Verbinden mit "." Klassifiziert und identifiziert werden können, kann das Risiko eines versehentlichen Tragens des Namens und infolgedessen eines Überschreibens des Logger-Betriebs verringert werden.

Es gibt noch eine weitere Funktion, die für Entwickler praktisch ist. Das heißt, der im oberen Logger festgelegte Inhalt wird vom untergeordneten Element geerbt.

Aufbau Von oben übernommen *
Protokollstufe der Logger-Instanz
Handler

Wenn Sie im vorherigen Beispiel die Protokollstufe von "gero. ** book **" ändern, ändern sich auch die Protokollstufen von "gero. ** book.web **" und "gero. ** book.api **". , Gero.book ". Sie können vom Debug-Status in den Nicht-Deubg-Status wechseln, indem Sie nur die obere Logger-Instanz wechseln, ohne die Einstellungen aller Logger-Instanzen zu ändern. Das ist nützlich.

Lass es uns bewegen.

logger_tree_exam_child1.py


import logging
import sys


def init_logger():
    # INIT
    global gero_book_logger
    global gero_question_logger
    global gero_book_web_logger
    # gero.book
    gero_book_logger = logging.getLogger('gero.book')
    gero_book_handler = logging.StreamHandler()
    gero_book_formatter = logging.Formatter(fmt='%(asctime)-15s [%(name)s] %(message)s')
    gero_book_handler.setFormatter(gero_book_formatter)
    gero_book_logger.addHandler(gero_book_handler)

    # gero.question
    gero_question_logger = logging.getLogger('gero_question')
    gero_question_handler = logging.StreamHandler()
    gero_question_formatter = logging.Formatter(fmt='%(asctime)-15s [%(name)s] %(message)s')
    gero_question_handler.setFormatter(gero_question_formatter)
    gero_question_logger.addHandler(gero_question_handler)

    # gero.book.web (gero.Machen Sie ein Kind aus Buch)
    gero_book_web_logger = logging.getLogger('gero.book.web')
    # handler,Formatierer nicht eingestellt


init_logger()

# PRINT
print('test 1-1: "gero.book.Gibt es ein Weblog?"', file=sys.stderr)
# SET LOG LEVEL (gero.book.Nicht im Web einstellen)
gero_book_logger.setLevel(logging.DEBUG)
gero_question_logger.setLevel(logging.INFO)

# gero.book
gero_book_logger.debug('debug now')
gero_book_logger.info('info now')
gero_book_logger.warning('warning now')
gero_book_logger.error('error now')
gero_book_logger.critical('critical now')

# gero.question
gero_question_logger.debug('debug now')
gero_question_logger.info('info now')
gero_question_logger.warning('warning now')
gero_question_logger.error('error now')
gero_question_logger.critical('critical now')

# gero.book.web
gero_book_web_logger.debug('debug now')
gero_book_web_logger.info('info now')
gero_book_web_logger.warning('warning now')
gero_book_web_logger.error('error now')
gero_book_web_logger.critical('critical now')

print('test 1-2: "gero.Wenn Sie die Fehlerstufe des Buchloggers ändern, wird gero verwendet.book.Wird sich das Niveau des Webs ändern?"', file=sys.stderr)
gero_book_logger.setLevel(logging.ERROR)

# gero.book.web
gero_book_web_logger.debug('debug now')
gero_book_web_logger.info('info now')
gero_book_web_logger.warning('warning now')
gero_book_web_logger.error('error now')
gero_book_web_logger.critical('critical now')

Das Ausführungsergebnis ist wie folgt.

test 1-1: "gero.book.Gibt es ein Weblog?"
2020-09-05 13:51:02,874 [gero.book] debug now
2020-09-05 13:51:02,875 [gero.book] info now
2020-09-05 13:51:02,875 [gero.book] warning now
2020-09-05 13:51:02,875 [gero.book] error now
2020-09-05 13:51:02,875 [gero.book] critical now
2020-09-05 13:51:02,875 [gero_question] info now
2020-09-05 13:51:02,875 [gero_question] warning now
2020-09-05 13:51:02,875 [gero_question] error now
2020-09-05 13:51:02,875 [gero_question] critical now
2020-09-05 13:51:02,875 [gero.book.web] debug now
2020-09-05 13:51:02,875 [gero.book.web] info now
2020-09-05 13:51:02,875 [gero.book.web] warning now
2020-09-05 13:51:02,875 [gero.book.web] error now
2020-09-05 13:51:02,876 [gero.book.web] critical now
test 1-2: "gero.Wenn Sie die Fehlerstufe des Buchloggers ändern, wird gero verwendet.book.Wird sich das Niveau des Webs ändern?"
2020-09-05 13:51:02,876 [gero.book.web] error now
2020-09-05 13:51:02,876 [gero.book.web] critical now

Process finished with exit code 0

Durch Ändern der Protokollstufe der übergeordneten Logger-Instanz können Sie feststellen, dass sich die Protokollausgabeebene des untergeordneten Protokolls ändert. Was ist also, wenn Sie Ihre eigene Protokollebene für die untergeordnete Logger-Instanz festlegen oder wenn Sie einen eigenen Handler für die untergeordnete Loggger-Instanz festlegen und die Protokollstufe für die übergeordnete Logger-Instanz ändern?

logger_tree_exam_child1.py


import logging
import sys

"""Wenn Sie Ihre eigene Protokollstufe für untergeordnete Logger-Instanzen festlegen
"""


def init_logger():
    # INIT
    global gero_book_logger
    global gero_book_web_logger
    # gero.book
    gero_book_logger = logging.getLogger('gero.book')
    gero_book_handler = logging.StreamHandler()
    gero_book_formatter = logging.Formatter(fmt='%(asctime)-15s [%(name)s] %(message)s')
    gero_book_handler.setFormatter(gero_book_formatter)
    gero_book_logger.addHandler(gero_book_handler)

    # gero.book.web (gero.Machen Sie ein Kind aus Buch)
    gero_book_web_logger = logging.getLogger('gero.book.web')
    # handler,Formatierer nicht eingestellt


init_logger()

# PRINT
print('test 2-1: "gero.book.Nachdem Sie die Protokollstufe für das Web separat eingestellt haben, klicken Sie auf gero.Ändern Sie die Protokollstufe des Buches"', file=sys.stderr)
# SET LOG LEVEL
gero_book_logger.setLevel(logging.DEBUG)
gero_book_web_logger.setLevel(logging.DEBUG)

print('Vorher ändern', file=sys.stderr)
# gero.book
gero_book_logger.debug('Sollte herauskommen')
gero_book_logger.info('Sollte herauskommen')
gero_book_logger.warning('Sollte herauskommen')
gero_book_logger.error('Sollte herauskommen')
gero_book_logger.critical('Sollte herauskommen')

# gero.book.web
gero_book_web_logger.debug('Sollte herauskommen')
gero_book_web_logger.info('Sollte herauskommen')
gero_book_web_logger.warning('Sollte herauskommen')
gero_book_web_logger.error('Sollte herauskommen')
gero_book_web_logger.critical('Sollte herauskommen')

print('Nach der veränderung', file=sys.stderr)
gero_book_logger.setLevel(logging.WARNING)

# gero.book
gero_book_logger.debug('Erscheint nicht')
gero_book_logger.info('Erscheint nicht')
gero_book_logger.warning('Sollte herauskommen')
gero_book_logger.error('Sollte herauskommen')
gero_book_logger.critical('Sollte herauskommen')

# gero.book.web
gero_book_web_logger.debug('Wirst du rauskommen? Erscheint nicht?')
gero_book_web_logger.info('Wirst du rauskommen? Erscheint nicht?')
gero_book_web_logger.warning('Sollte herauskommen')
gero_book_web_logger.error('Sollte herauskommen')
gero_book_web_logger.critical('Sollte herauskommen')

Das Ausführungsergebnis ist wie folgt. Es scheint, dass die für die untergeordnete Instanz "gero.book.web" festgelegte Protokollstufe funktioniert.

test 2-1: "gero.book.Nachdem Sie die Protokollstufe für das Web separat eingestellt haben, klicken Sie auf gero.Ändern Sie die Protokollstufe des Buches"
Vorher ändern
2020-09-06 03:11:27,524 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Sollte herauskommen
Nach der veränderung
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book]Sollte herauskommen
2020-09-06 03:11:27,525 [gero.book.web]Wirst du rauskommen? Erscheint nicht?
2020-09-06 03:11:27,526 [gero.book.web]Wirst du rauskommen? Erscheint nicht?
2020-09-06 03:11:27,526 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,526 [gero.book.web]Sollte herauskommen
2020-09-06 03:11:27,526 [gero.book.web]Sollte herauskommen

Process finished with exit code 0

Fügen wir nun einen Handler zu "gero.book.web" hinzu. Dieses Mal legen wir die Protokollebene für "gero.book.web" nicht fest.

logger_tree_exam_child3.py


import logging
import sys

"""Wenn Sie Ihren eigenen Handler für eine untergeordnete Loggger-Instanz festlegen
"""


def init_logger():
    # INIT
    global gero_book_logger
    global gero_book_web_logger
    # gero.book
    gero_book_logger = logging.getLogger('gero.book')
    gero_book_handler = logging.StreamHandler()
    gero_book_formatter = logging.Formatter(fmt='%(asctime)-15s [%(name)s] %(message)s')
    gero_book_handler.setFormatter(gero_book_formatter)
    gero_book_logger.addHandler(gero_book_handler)

    # gero.book.web (gero.Machen Sie ein Kind aus Buch)
    gero_book_web_logger = logging.getLogger('gero.book.web')


init_logger()

# PRINT
print('test 3-1: "gero.book.Nachdem Sie die Protokollstufe für das Web separat eingestellt haben, klicken Sie auf gero.Ändern Sie die Protokollstufe des Buches"', file=sys.stderr)
# SET LOG LEVEL
gero_book_logger.setLevel(logging.DEBUG)

print('Vorher ändern', file=sys.stderr)
# gero.book
gero_book_logger.debug('Sollte herauskommen')
gero_book_logger.info('Sollte herauskommen')
gero_book_logger.warning('Sollte herauskommen')
gero_book_logger.error('Sollte herauskommen')
gero_book_logger.critical('Sollte herauskommen')

# gero.book.web
gero_book_web_logger.debug('Sollte herauskommen')
gero_book_web_logger.info('Sollte herauskommen')
gero_book_web_logger.warning('Sollte herauskommen')
gero_book_web_logger.error('Sollte herauskommen')
gero_book_web_logger.critical('Sollte herauskommen')

print('Nach der veränderung', file=sys.stderr)
print('- gero.book.Handler zur Webseite hinzugefügt', file=sys.stderr)
gero_book_web_handler = logging.StreamHandler()
gero_book_web_formatter = logging.Formatter(fmt='%(asctime)-15s [%(name)s] ### this is web ### %(message)s')
gero_book_web_handler.setFormatter(gero_book_web_formatter)
gero_book_web_logger.addHandler(gero_book_web_handler)
print('- gero.Ändern Sie die Buchprotokollstufe in WARNUNG', file=sys.stderr)
gero_book_logger.setLevel(logging.WARNING)

# gero.book
gero_book_logger.debug('Erscheint nicht')
gero_book_logger.info('Erscheint nicht')
gero_book_logger.warning('Sollte herauskommen')
gero_book_logger.error('Sollte herauskommen')
gero_book_logger.critical('Sollte herauskommen')

# gero.book.web
gero_book_web_logger.debug('Wirst du rauskommen? Erscheint nicht?')
gero_book_web_logger.info('Wirst du rauskommen? Erscheint nicht?')
gero_book_web_logger.warning('Sollte herauskommen')
gero_book_web_logger.error('Sollte herauskommen')
gero_book_web_logger.critical('Sollte herauskommen')

print(gero_book_web_logger.handlers)

Das Ausführungsergebnis ist wie folgt. Es gibt zwei Protokolle für "gero.book.web". Da der hinzugefügte Handler wirklich "hinzugefügt" wird, besteht das Verhalten darin, dass sowohl der Handler des übergeordneten Loggers als auch der ursprüngliche Handler ausgegeben werden. Außerdem wurde das Protokoll des ursprünglichen Handlers gemäß der übergeordneten LogLevel verschoben.

test 3-1: "gero.book.Nachdem Sie die Protokollstufe für das Web separat eingestellt haben, klicken Sie auf gero.Ändern Sie die Protokollstufe des Buches"
Vorher ändern
2020-09-06 03:21:11,709 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,709 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book.web]Sollte herauskommen
Nach der veränderung
- gero.book.Handler zur Webseite hinzugefügt
- gero.Ändern Sie die Buchprotokollstufe in WARNUNG
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,710 [gero.book]Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web] ### this is web ###Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web] ### this is web ###Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web]Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web] ### this is web ###Sollte herauskommen
2020-09-06 03:21:11,711 [gero.book.web]Sollte herauskommen
[<StreamHandler <stderr> (NOTSET)>]

Process finished with exit code 0

Im obigen Beispielcode habe ich am Ende einen kleinen "print (gero_book_web_logger.handlers)" geschrieben. Das Ergebnis dieser Ausführung ist "[<StreamHandler (NOTSET)>]". Es gibt nur eins. Dies bedeutet, dass auf der unteren Ebene der Handler nicht auf der höheren Ebene eingestellt ist. Die Eltern-Kind-Beziehung zwischen Logger-Instanzen ähnelt eher dem Verhalten, dass eine untergeordnete Logger-Instanz weiß, wer ihre übergeordnete Logger-Instanz ist, und ruft auch ihre Protokollierungsmethode auf (Klassenvererbung). Manchmal verhält es sich so, als würde eine Methode auf der Oberklassenseite einer Methode aufgerufen, die in einer untergeordneten Klasse überschrieben wird. Diese Implementierung basiert auf der folgenden Implementierung der Methode callHandlers ().

logging/__init__.py


#Abkürzung
    def callHandlers(self, record):
        #Abkürzung
        c = self
        found = 0
        while c:
            for hdlr in c.handlers:
                found = found + 1
                if record.levelno >= hdlr.level:
                    hdlr.handle(record)
            if not c.propagate:
                c = None    #break out
            else:
                c = c.parent
        #Abkürzung

Überprüfen Sie die Logger-Instanzen

Der von getLogger (name = None) angegebene Name ist also nicht nur ein Name, sondern wie der absolute Pfad von Logger und hierarchisch. Darüber hinaus ist ersichtlich, dass die auf der höheren Ebene vorgenommenen Einstellungen vom Kind geerbt werden und dass die vom Kind vorgenommenen Einstellungen Vorrang haben.

Aufgrund dieser Aktionen kann ich mir vorstellen, dass die Verwendung einfacher ist, wenn Sie sie wie folgt verwenden.

  1. Geben Sie für die Protokollierung, z. B. die Protokollierung ohne Zweck, einen Handler für eine höhere Logger-Instanz an.
  2. Mit Ausnahme von Situationen, in denen die untergeordnete Logger-Instanz eine andere Protokollebene für einen bestimmten Zweck ausspucken soll, ist es einfacher, sie zu ändern, indem Sie sie mit der übergeordneten Protokollebene steuern, ohne die Protokollebene festzulegen (vorausgesetzt, dev → prd usw.). Wenn).
  1. Wenn Sie den Handler entsprechend dem Zweck jeder Logger-Instanz so einstellen, dass Protokolle ausgespuckt werden, ist es einfacher, die Protokolle zu verwenden (Sie können beispielsweise nur das Zugriffsprotokoll des Dienstes auf eine dedizierte Datei ausspucken, um die Aggregation zu vereinfachen, oder ein dediziertes Ausnahmeprotokoll erstellen).
  2. Der obige Vorgang muss nur einmal im Initialisierungsprozess ausgeführt werden, wenn die Anwendung gestartet wird. Die bereits von logging.get_logger (" path.to.logger ") festgelegte Instanz wird abgerufen.

Nachwort

In diesem Artikel wird zunächst erwähnt, wie die Protokollierungsfunktion (dh der Root-Logger) des Protokollierungsmoduls, das auch in der offiziellen Python-Dokumentation erwähnt wird, zur Organisation der Idee verwendet wird. Ich persönlich empfehle jedoch nicht, den Root-Logger zu verwenden. Es ist einfach, etwas wie "Wenn Sie versuchen, die Protokolle eines von Ihnen geschriebenen Programms auszuspucken, erhalten Sie viele Protokolle aus anderen Bibliotheken, die Sie importieren, und Sie sind auf Disk Full gestorben."

Auf der anderen Seite sind Protokollierungs- und Protokollierungsbibliotheken so tiefgreifend, dass sie nicht einfach zu schreiben sind. Deshalb habe ich mich entschlossen, von Grund auf neu zu lernen und sie im Artikel zu belassen.

Links

Unten verschiedene Licks.

--logging --- Protokollierungsfunktion für Python

Recommended Posts

Erfahren Sie mehr über die Protokollierung mit dem Python-Protokollierungsmodul ①
Verwendung des Python-Protokollierungsmoduls
Die Geschichte der Verwendung von Python reduziert
Bearbeiten Sie WAV-Dateien mit dem Wave-Modul von Python
Erfahren Sie mehr über das Programmieren
Erste Schritte mit Pythons Ast-Modul (Verwenden von NodeVisitor)
Erfahren Sie mehr über Go Slices
Versuchen Sie es mit dem Feed-Parser von Python.
Versuchen Sie es mit Pythons Tkinter
Erfahren Sie mehr über die Druckfunktion und die Zeichenfolgen von Python für Anfänger.
Denken Sie also an die Protokollierung
So geben Sie zusätzliche Informationen aus, wenn Sie Protokolle mit dem Protokollierungsmodul von Python ausgeben
Hinweise zum SQLite3-Modul von Python
Über das Python-Modul venv
Senden Sie E-Mails mit Pythons smtplib