Einführung
Dieser Abschnitt gibt eine kurze Einführung in das Protokollierungsmodul.
This tutorial is from open-source community. Access the source code
💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken
Dieser Abschnitt gibt eine kurze Einführung in das Protokollierungsmodul.
Das Protokollierungsmodul
ist ein Modul der Standardbibliothek zur Aufzeichnung von diagnostischen Informationen. Es ist auch ein sehr umfangreiches Modul mit einer Vielzahl an sophistizierter Funktionalität. Wir werden ein einfaches Beispiel zeigen, um seine Nützlichkeit zu veranschaulichen.
In den Übungen haben wir eine Funktion parse()
geschrieben, die ungefähr so aussah:
## fileparse.py
def parse(f, types=None, names=None, delimiter=None):
records = []
for line in f:
line = line.strip()
if not line: continue
try:
records.append(split(line,types,names,delimiter))
except ValueError as e:
print("Couldn't parse :", line)
print("Reason :", e)
return records
Richten Sie Ihre Aufmerksamkeit auf die try-except
-Anweisung. Was sollten Sie im except
-Block tun?
Sollten Sie eine Warnmeldung ausgeben?
try:
records.append(split(line,types,names,delimiter))
except ValueError as e:
print("Couldn't parse :", line)
print("Reason :", e)
Oder ignorieren Sie es stillschweigend?
try:
records.append(split(line,types,names,delimiter))
except ValueError as e:
pass
Keine der Lösungen ist zufriedenstellend, da Sie oft beide Verhaltensweisen (benutzerauswählbar) möchten.
Das Protokollierungsmodul
kann dies beheben.
## fileparse.py
import logging
log = logging.getLogger(__name__)
def parse(f,types=None,names=None,delimiter=None):
...
try:
records.append(split(line,types,names,delimiter))
except ValueError as e:
log.warning("Couldn't parse : %s", line)
log.debug("Reason : %s", e)
Der Code wird geändert, um Warnmeldungen auszugeben oder ein spezielles Logger
-Objekt. Das mit logging.getLogger(__name__)
erstellte.
Erstellen Sie ein Logger-Objekt.
log = logging.getLogger(name) ## name ist ein String
Ausgeben von Protokollierungsnachrichten.
log.critical(message [, args])
log.error(message [, args])
log.warning(message [, args])
log.info(message [, args])
log.debug(message [, args])
Jede Methode stellt ein unterschiedliches Schwerelevel dar.
Alle erzeugen eine formattierte Protokollierungsnachricht. args
wird mit dem %
-Operator verwendet, um die Nachricht zu erstellen.
logmsg = message % args ## In das Protokoll geschrieben
Das Protokollierungsverhalten wird separat konfiguriert.
## main.py
...
if __name__ == '__main__':
import logging
logging.basicConfig(
filename = 'app.log', ## Protokollausgabedatei
level = logging.INFO, ## Ausgabebereich
)
Normalerweise ist dies eine einmalige Konfiguration beim Programmstart. Die Konfiguration ist getrennt von dem Code, der die Protokollierungsaufrufe macht.
Die Protokollierung ist hochgradig konfigurierbar. Sie können jedes Aspekt davon anpassen: Ausgabedateien, Ebenen, Nachrichtenformate usw. Der Code, der die Protokollierung verwendet, muss sich jedoch nicht darum kümmern.
In fileparse.py
gibt es einige Fehlerbehandlungen, die mit Ausnahmen aufgrund von schlechtem Input zusammenhängen. Es sieht so aus:
## fileparse.py
import csv
def parse_csv(lines, select=None, types=None, has_headers=True, delimiter=',', silence_errors=False):
'''
Parse a CSV file into a list of records with type conversion.
'''
if select and not has_headers:
raise RuntimeError('select requires column headers')
rows = csv.reader(lines, delimiter=delimiter)
## Read the file headers (if any)
headers = next(rows) if has_headers else []
## If specific columns have been selected, make indices for filtering and set output columns
if select:
indices = [ headers.index(colname) for colname in select ]
headers = select
records = []
for rowno, row in enumerate(rows, 1):
if not row: ## Skip rows with no data
continue
## If specific column indices are selected, pick them out
if select:
row = [ row[index] for index in indices]
## Apply type conversion to the row
if types:
try:
row = [func(val) for func, val in zip(types, row)]
except ValueError as e:
if not silence_errors:
print(f"Row {rowno}: Couldn't convert {row}")
print(f"Row {rowno}: Reason {e}")
continue
## Make a dictionary or a tuple
if headers:
record = dict(zip(headers, row))
else:
record = tuple(row)
records.append(record)
return records
Bemerken Sie die print
-Anweisungen, die diagnostische Nachrichten ausgeben. Das Ersetzen dieser print
-Anweisungen durch Protokollierungsoperationen ist relativ einfach. Ändern Sie den Code wie folgt:
## fileparse.py
import csv
import logging
log = logging.getLogger(__name__)
def parse_csv(lines, select=None, types=None, has_headers=True, delimiter=',', silence_errors=False):
'''
Parse a CSV file into a list of records with type conversion.
'''
if select and not has_headers:
raise RuntimeError('select requires column headers')
rows = csv.reader(lines, delimiter=delimiter)
## Read the file headers (if any)
headers = next(rows) if has_headers else []
## If specific columns have been selected, make indices for filtering and set output columns
if select:
indices = [ headers.index(colname) for colname in select ]
headers = select
records = []
for rowno, row in enumerate(rows, 1):
if not row: ## Skip rows with no data
continue
## If specific column indices are selected, pick them out
if select:
row = [ row[index] for index in indices]
## Apply type conversion to the row
if types:
try:
row = [func(val) for func, val in zip(types, row)]
except ValueError as e:
if not silence_errors:
log.warning("Row %d: Couldn't convert %s", rowno, row)
log.debug("Row %d: Reason %s", rowno, e)
continue
## Make a dictionary or a tuple
if headers:
record = dict(zip(headers, row))
else:
record = tuple(row)
records.append(record)
return records
Jetzt, nachdem Sie diese Änderungen vorgenommen haben, versuchen Sie, einige Ihres Codes mit schlechtem Daten zu verwenden.
>>> import report
>>> a = report.read_portfolio('missing.csv')
Row 4: Bad row: ['MSFT', '', '51.23']
Row 7: Bad row: ['IBM', '', '70.44']
>>>
Wenn Sie nichts tun, erhalten Sie nur Protokollierungsnachrichten für das WARNING
-Level und darüber. Die Ausgabe wird wie einfache print
-Anweisungen aussehen. Wenn Sie jedoch das Protokollierungsmodul konfigurieren, erhalten Sie zusätzliche Informationen über die Protokollierungsebenen, das Modul und mehr. Tippen Sie diese Schritte, um das zu sehen:
>>> import logging
>>> logging.basicConfig()
>>> a = report.read_portfolio('missing.csv')
WARNING:fileparse:Row 4: Bad row: ['MSFT', '', '51.23']
WARNING:fileparse:Row 7: Bad row: ['IBM', '', '70.44']
>>>
Sie werden bemerken, dass Sie die Ausgabe der log.debug()
-Operation nicht sehen. Tippen Sie dies, um das Level zu ändern.
>>> logging.getLogger('fileparse').setLevel(logging.DEBUG)
>>> a = report.read_portfolio('missing.csv')
WARNING:fileparse:Row 4: Bad row: ['MSFT', '', '51.23']
DEBUG:fileparse:Row 4: Reason: invalid literal for int() with base 10: ''
WARNING:fileparse:Row 7: Bad row: ['IBM', '', '70.44']
DEBUG:fileparse:Row 7: Reason: invalid literal for int() with base 10: ''
>>>
Schalten Sie alle, außer die kritischsten Protokollierungsnachrichten, aus:
>>> logging.getLogger('fileparse').setLevel(logging.CRITICAL)
>>> a = report.read_portfolio('missing.csv')
>>>
Um der Protokollierung in einer Anwendung hinzuzufügen, müssen Sie ein Mechanismus haben, um das Protokollierungsmodul im Hauptmodul zu initialisieren. Ein Möglichkeit dazu ist, Code für die Einrichtung wie folgt zu verwenden:
## This file sets up basic configuration of the logging module.
## Change settings here to adjust logging output as needed.
import logging
logging.basicConfig(
filename = 'app.log', ## Name der Protokolldatei (lassen Sie weg, um stderr zu verwenden)
filemode = 'w', ## Dateimodus (verwenden Sie 'a', um anzuhängen)
level = logging.WARNING, ## Protokollierungslevel (DEBUG, INFO, WARNING, ERROR oder CRITICAL)
)
Wiederum müssen Sie diesen Code an einem Ort in den Startschritten Ihres Programms platzieren. Beispielsweise, wo würden Sie diesen Code in Ihrem report.py
-Programm platzieren?
Herzlichen Glückwunsch! Sie haben das Protokollierungslabor abgeschlossen. Sie können in LabEx weitere Labs absolvieren, um Ihre Fähigkeiten zu verbessern.