Einführung
Beim Schreiben von Code geht es darum, Probleme zu lösen, aber nicht jedes Drawback ist vorhersehbar. In der realen Welt stößt Ihre Software program auf unerwartete Situationen: fehlende Dateien, ungültige Benutzereingaben, Netzwerk -Zeitüberschreitungen oder sogar Hardwarefehler. Aus diesem Grund ist der Umgang mit Fehlern nicht nur ein schöner Have. Es ist ein kritischer Teil des Aufbaus robuster und zuverlässiger Produktionsanwendungen.
Stellen Sie sich eine E-Commerce-Web site vor. Ein Kunde gibt eine Bestellung auf, aber während des Kasseprozesses tritt ein Datenbankverbindungsproblem auf. Ohne richtig FehlerbehandlungDieses Drawback kann dazu führen, dass die Anwendung zum Absturz gebracht wird, wodurch der Kunden frustriert und die Transaktion unvollständig ist. Schlimmer noch, es könnte zu inkonsistenten Daten führen, was zu noch größeren Problemen in der ganzen Linie führt. Daher ist die Handhabung des Fehlers eine grundlegende Fähigkeit für jeden Python -Entwickler, der Code für die Produktion schreiben möchte.
Ein guter Fehlerbehebung geht jedoch auch Hand in Hand mit einem guten Protokollierungssystem. Es ist selten, Zugang zur Konsole zu haben, wenn der Code in der Produktion ausgeführt wird. Es gibt additionally keine Likelihood, dass Ihr Druck von irgendjemandem gesehen wird. Um sicherzustellen, dass Sie Ihre Anwendung überwachen und alle Vorfälle untersuchen können, müssen Sie ein Protokollierungssystem einrichten. Hier die loguru Paket kommt ins Spiel, das ich in diesem Artikel vorstellen werde.
Ich – wie gehe ich mit Python -Fehlern um?
In diesem Teil präsentiere ich die besten Praktiken des Fehlerhandlings in Pythonaus Versuchsblöcken und der Verwendung von elevate
zu dem lastly
Stellungnahme. Diese Konzepte helfen Ihnen dabei, sauberer, wartbarerer Code zu schreiben, der für eine Produktionsumgebung geeignet ist.
Der versuchen Blöcke
Der Versuchsblock ist das Hauptwerkzeug für den Umgang mit Fehlern in Python. Sie ermöglichen es Ihnen, potenzielle Fehler während der Codeausführung zu fangen und das Programm zu verhindern.
def divide(a, b):
attempt:
return a / b
besides ZeroDivisionError:
print(f"Solely Chuck Norris can divide by 0!")
In dieser trivialen Funktion ermöglicht der Attempt-Besides-Block, dass der durch eine Teilung durch 0 verursachte Fehler abgefangen wird. Der Code im Attempt -Block wird ausgeführt, und wenn ein Fehler auftritt ZeroDivisionError
und drucken Sie eine Nachricht. Aber nur diese Artwork von Fehler wird gefangen. Zum Beispiel wenn B ist eine Zeichenfolge, ein Fehler tritt auf. Um dies zu vermeiden, können Sie eine hinzufügen TypeError
. Es ist additionally wichtig, alle möglichen Fehler zu testen.
Die Funktion wird:
def divide(a, b):
attempt:
return a / b
besides ZeroDivisionError:
print(f"Solely Chuck Norris can divide by 0!")
besides TypeError:
print("Don't evaluate apples and orange!")
Erhöhen Sie eine Ausnahme
Sie können die Erhöhungserklärung verwenden, um eine Ausnahme manuell zu steigern. Dies ist nützlich, wenn Sie einen benutzerdefinierten Fehler melden oder Ihrem Code eine bestimmte Einschränkung auferlegen möchten.
def divide(a, b):
if b == 0:
elevate ValueError("Solely Chuck Norris can divide by 0!")
return a / b
attempt:
end result = divide(10, 0)
besides ValueError as e:
print(f"Error: {e}")
besides TypeError:
print("Don't evaluate apples and orange!")
In diesem Beispiel a ValueError
Die Ausnahme wird ausgelöst, wenn der Divisor Null ist. Auf diese Weise können Sie die Fehlerbedingungen explizit steuern. In der Druckfunktion wird die Nachricht sein. “Fehler: Nur Chuck Norris kann sich um 0 teilen!“.
Einige der häufigsten Ausnahmen
ValueError: Die Artwork eines Wertes ist korrekt, aber sein Wert ist ungültig.
attempt:
quantity = math.sqrt(-10)
besides ValueError:
print("It is too complicated to be actual!")
KeyError: Versuchen Sie, auf einen Schlüssel zuzugreifen, der in einem Wörterbuch nicht existiert.
knowledge = {"identify": "Alice"}
attempt:
age = knowledge("age")
besides KeyError:
print("By no means ask a girl her age!")
IndexError: Versuch, in einer Liste auf einen nicht existierenden Index zuzugreifen.
gadgets = (1, 2, 3)
attempt:
print(gadgets(3))
besides IndexError:
print("You overlook that indexing begins at 0, do not you?")
Typeerror: Durchführen eines Betriebs an inkompatiblen Typen.
attempt:
end result = "textual content" + 5
besides TypeError:
print("Don't evaluate apples and orange!")
FilenotFoundError: Versuch, eine nicht existierende Datei zu öffnen.
attempt:
with open("notexisting_file.txt", "r") as file:
content material = file.learn()
besides FileNotFoundError:
print("Are you certain of your path?")
Benutzerdefinierte Fehler: Sie können vordefinierte Ausnahmen auslösen oder auch Ihre eigenen Ausnahmeklassen definieren:
class CustomError(Exception):
go
attempt:
elevate CustomError("This can be a customized error")
besides CustomError as e:
print(f"Catched error: {e}")
Sauber mit dem Endlich Stellungnahme
Der lastly
Block wird in jedem Fall ausgeführt, unabhängig davon, ob der Fehler aufgetreten ist oder nicht. Es wird häufig verwendet, um Reinigungsaktionen durchzuführen, z. B. das Schließen einer Verbindung zu einer Datenbank oder die Freisetzung von Ressourcen.
import sqlite3
attempt:
conn = sqlite3.join("users_db.db") # Connect with a database
cursor = conn.cursor()
cursor.execute("SELECT * FROM customers") # Execute a question
outcomes = cursor.fetchall() # Get results of the question
print(outcomes)
besides sqlite3.DatabaseError as e:
print("Database error:", e)
lastly:
print("Closing the database connection.")
if 'conn' in locals():
conn.shut() # Ensures the connection is closed
Greatest Practices für die Fehlerbehandlung
- Fang bestimmte Ausnahmen fangen: Vermeiden Sie die Verwendung eines Generikums außer Block, ohne eine Ausnahme anzugeben, da dies unerwartete Fehler maskieren kann. Zulassen Sie die Ausnahme vor:
# Unhealthy follow
attempt:
end result = 10 / 0
besides Exception as e:
print(f"Error: {e}")
# Good follow
attempt:
end result = 10 / 0
besides ZeroDivisionError as e:
print(f"Error: {e}")
- Geben Sie explizite Nachrichten an: Fügen Sie klare und beschreibende Nachrichten hinzu, wenn Sie Ausnahmen anheben oder bearbeiten.
- Vermeiden Sie stille Misserfolge: Wenn Sie eine Ausnahme einnehmen, stellen Sie sicher, dass sie protokolliert oder wieder aufgenommen wird, damit sie nicht unbemerkt bleibt.
import logging
logging.basicConfig(stage=logging.ERROR)
attempt:
end result = 10 / 0
besides ZeroDivisionError:
logging.error("Division by zero detected.")
- Verwenden
else
Undlastly
Blöcke: Derelse
Block läuft nur, wenn in der keine Ausnahme erhoben wirdattempt
Block.
attempt:
end result = 10 / 2
besides ZeroDivisionError:
logging.error("Division by zero detected.")
else:
logging.data(f"Success: {end result}")
lastly:
logging.data("Finish of processing.")
II – Wie gehe ich mit Python -Protokollen um?
Eine gute Fehlerbehandlung ist eine Sache, aber wenn niemand weiß, dass ein Fehler aufgetreten ist, geht der springende Punkt verloren. Wie in der Einführung erläutert, wird der Monitor selten konsultiert oder sogar gesehen, wenn ein Programm in der Produktion ausgeführt wird. Niemand wird Druck sehen. Daher muss ein guter Fehlerbehebung von einem guten Protokollierungssystem begleitet werden.
Was sind Protokolle?
Protokolle sind Datensätze von Nachrichten, die von einem Programm generiert wurden, um die Ereignisse zu verfolgen, die während seiner Ausführung stattfinden. Diese Nachrichten können Informationen zu Fehlern, Warnungen, erfolgreichen Aktionen, Prozessmeilensteinen oder anderen relevanten Ereignissen enthalten. Protokolle sind für das Debuggen, die Verfolgung der Leistung und die Überwachung der Gesundheit einer Anwendung unerlässlich. Sie ermöglichen es den Entwicklern zu verstehen, was in einem Programm vor sich geht, ohne ihre Ausführung unterbrechen zu müssen, sodass es einfacher ist, Probleme zu lösen und die Software program kontinuierlich zu verbessern.
Das Loguru -Paket
Python hat bereits ein natives Protokollierungspaket: Protokollierung. Wir bevorzugen jedoch das Loguru -Paket, das viel einfacher zu verwenden und einfacher zu konfigurieren ist. Tatsächlich ist die vollständige Ausgangsformatierung bereits vorkonfiguriert.
from loguru import logger
logger.debug("A reasonably debug message!")

Alle wichtigen Elemente sind direkt in die Nachricht enthalten:
- Zeitstempel
- Protokollebene, die die Ernsthaftigkeit der Nachricht angibt.
- Dateispeicherort, Modul und Zeilennummer. In diesem Beispiel ist der Dateispeicherort __main__, da er direkt aus der Befehlszeile ausgeführt wurde. Das Modul ist
aufgrund der Tatsache, dass sich das Protokoll nicht in einer Klasse oder Funktion befindet. - Die Nachricht.
Die unterschiedlichen Protokollierungsstufen
Es gibt mehrere Protokollebenen, die die Bedeutung der angezeigten Nachricht berücksichtigen müssen (was in einem Druck komplizierter ist). Jede Ebene hat einen Namen und eine zugehörige Nummer:
- VERFOLGEN (5): Wird verwendet, um detaillierte Informationen über den Ausführungspfad des Programms für diagnostische Zwecke aufzuzeichnen.
- DEBUGGEN (10): Wird von Entwicklern verwendet, um Nachrichten für Debugging -Zwecke aufzuzeichnen.
- INFO (20): Wird zum Aufzeichnen von Informationen zur Beschreibung des normalen Programmbetriebs verwendet.
- ERFOLG (25): Ähnlich wie bei Data, aber verwendet, um den Erfolg einer Operation anzuzeigen.
- WARNUNG (30): Wird verwendet, um ein ungewöhnliches Ereignis anzugeben, bei dem möglicherweise weitere Untersuchungen erforderlich sind.
- FEHLER (40): Wird verwendet, um Fehlerbedingungen aufzuzeichnen, die einen bestimmten Vorgang beeinflusst haben.
- KRITISCH (50): Wird verwendet, um Fehlerbedingungen aufzuzeichnen, die verhindern, dass eine Hauptfunktion funktioniert.
Das Paket behandelt auf natürliche Weise unterschiedliche Formatierung, je nach verwendeten Niveau
from loguru import logger
logger.hint("A hint message.")
logger.debug("A debug message.")
logger.data("An data message.")
logger.success("Successful message.")
logger.warning("A warning message.")
logger.error("An error message.")
logger.vital("A vital message.")

Die Hint -Nachricht wurde nicht angezeigt, da die von Loguru verwendete Standardmindeststufe debugu ist. Es ignoriert daher alle Nachrichten auf niedrigeren Ebenen.
Es ist möglich, neue Protokollpegel mit der Pegelmethode zu definieren, und wird mit der Protokollmethode verwendet
logger.stage("FATAL", no=60, colour="<pink>", icon="!!!")
logger.log("FATAL", "A FATAL occasion has simply occurred.")
- Title: Der Title der Protokollebene.
- Nein: Der entsprechende Schweregradwert (muss eine Ganzzahl sein).
- Farbe: Farbe Markup.
- Image: Das Degree -Image.
Die Logger -Konfiguration
Es ist möglich, einen Logger mit einer neuen Konfiguration neu zu erstellen, indem Sie den alten mit dem löschen take away
Befehl und Generieren eines neuen Loggers mit einer neuen Konfiguration mit dem add
Funktion. Diese Funktion nimmt die folgenden Argumente an:
- Waschbecken (obligatorisch): Gibt ein Ziel für jeden vom Logger erstellten Datensatz an. Standardmäßig wird dieser Wert auf festgelegt
sys.stderr
(was der Standardfehlerausgabe entspricht). Wir können auch alle Ausgaben in einer „.log“ -Datei speichern (außer wenn Sie einen Protokollsammler haben). - Ebene: Legt die minimale Protokollierungsstufe für den Rekorder fest.
- Format: ist nützlich, um ein benutzerdefiniertes Format für Ihre Protokolle zu definieren. Um die Färbung der Protokolle im Terminal aufrechtzuerhalten, muss dies angegeben werden (siehe Beispiel unten).
- Filter: wird verwendet, um festzustellen, ob ein Protokoll aufgezeichnet werden sollte oder nicht.
- folellieren: Nimmt einen booleschen Wert an und bestimmt, ob die Anschlussfärbung aktiviert werden sollte oder nicht.
- serialisieren: verursacht das Protokoll im JSON -Format, wenn es auf festgelegt ist
True
. - Backtrace: Ermittelt, ob die Ausnahmeverfolgung über den Punkt hinausgehen sollte, an dem der Fehler aufgezeichnet wurde, um die Fehlerbehebung zu erleichtern.
- diagnostizieren: Ermittelt, ob in der Ausnahmespur Variablenwerte angezeigt werden sollten. Diese Choice muss auf festgelegt werden
False
in Produktionsumgebungen, so dass keine sensiblen Informationen durchgesickert sind. - Enqueue: Wenn diese Choice aktiviert ist, werden die Protokolldatensätze in einer Warteschlange platziert, um Konflikte zu vermeiden, wenn mehrere Prozesse mit demselben Ziel verbunden sind.
- fangen: Wenn ein unerwarteter Fehler auftritt, wenn Sie eine Verbindung zum Server angegeben haben, können Sie ihn erkennen, indem Sie diese Choice an die Choice festlegen
True
. Der Fehler wird im Standardfehler angezeigt.
import sys
from loguru import logger
logger_format = (
"{time:YYYY-MM-DD HH:mm:ss.SSS} | "
"{stage: <8} | "
"{identify}:{perform}:{line}"
)
logger.take away()
logger.add(sys.stderr, format=logger_format)
Notiz:
Farben verschwinden in einer Datei. Dies liegt daran, dass es Sonderzeichen gibt (genannt Ansi Codes), die Farben im Terminal anzeigen, aber diese Formatierung gibt es in den Dateien nicht.
Fügen Sie Protokolle Kontext hinzu
Für komplexe Anwendungen kann es nützlich sein, den Protokollen weitere Informationen hinzuzufügen, um die Sortierung zu ermöglichen und die Fehlerbehebung zu erleichtern.
Wenn ein Benutzer beispielsweise eine Datenbank ändert, kann es nützlich sein, die Benutzer -ID zusätzlich zu den Änderungsinformationen zu haben.
Bevor Sie mit der Aufzeichnung von Kontextdaten beginnen, müssen Sie sicherstellen, dass die {further}
Die Richtlinie ist in Ihrem benutzerdefinierten Format enthalten. Diese Variable ist ein Python -Wörterbuch, das Kontextdaten für jeden Protokolleintrag enthält (falls zutreffend).
Hier ist ein Beispiel für eine Anpassung, bei der ein Additional user_id
wird hinzugefügt. In diesem Format die Farben.
import sys
from loguru import logger
logger_format = (
"<inexperienced>{time:YYYY-MM-DD HH:mm:ss.SSS}</inexperienced> | "
"<stage>{stage: <8}</stage> | "
"<cyan>{identify}</cyan>:<cyan>{perform}</cyan>:<cyan>{line}</cyan> | "
"Person ID: {further(user_id)} - <stage>{message}</stage>"
)
logger.configure(further={"user_id": ""}) # Default worth
logger.take away()
logger.add(sys.stderr, format=logger_format)
Es ist nun möglich, die Bind -Methode zu verwenden, um einen untergeordneten Logger zu erstellen, der alle Daten vom übergeordneten Logger erbt.
childLogger = logger.bind(user_id="001")
childLogger.data("Right here a message from the kid logger")
logger.data("Right here a message from the dad or mum logger")

Eine andere Möglichkeit, dies zu tun, besteht darin, die Kontextualisierungsmethode in einem mit Block zu verwenden.
with logger.contextualize(user_id="001"):
logger.data("Right here a message from the logger with user_id 001")
logger.data("Right here a message from the logger with out user_id")

Anstelle des Blocks können Sie a verwenden Dekorateur. Der vorhergehende Code wird dann
@logger.contextualize(user_id="001")
def child_logger():
logger.data("Right here a message from the logger with user_id 001")
child_logger()
logger.data("Right here a message from the logger with out user_id")
Die Fangmethode
Fehler können automatisch protokolliert werden, wenn sie unter Verwendung der Fangmethode auftreten.
def take a look at(x):
50/x
with logger.catch():
take a look at(0)

Aber es ist einfacher, diese Methode als Dekorateur zu verwenden. Dies führt im folgenden Code
@logger.catch()
def take a look at(x):
50/x
take a look at(0)
Die Protokolldatei
Eine Produktionsanwendung ist so konzipiert, dass sie kontinuierlich und ununterbrochen ausgeführt wird. In einigen Fällen ist es wichtig, das Verhalten der Datei vorherzusagen. Andernfalls müssen Sie im Falle eines Fehlers Seiten mit Protokollen konsultieren.
Hier sind die unterschiedlichen Bedingungen, unter denen eine Datei geändert werden kann:
- Drehung: Gibt eine Bedingung an, unter der die aktuelle Protokolldatei geschlossen und eine neue Datei erstellt wird. Dieser Zustand kann ein int, ein datetime oder ein str. STR wird empfohlen, da es einfacher zu lesen ist.
- Zurückbehaltung: Gibt an, wie lange jede Protokolldatei aufbewahrt werden soll, bevor sie aus dem Dateisystem gelöscht wird.
- Kompression: Die Protokolldatei wird in das angegebene Komprimierungsformat konvertiert, wenn diese Choice aktiviert ist.
- Verzögerung: Wenn diese Choice auf True gesetzt ist, wird die Erstellung einer neuen Protokolldatei bis zur ersten Protokollnachricht verzögert.
- ModusAnwesend PufferungAnwesend Codierung : Parameter, die an die Python -Funktion übergeben werden, öffnen und bestimmen, wie Python Protokolldateien öffnet.
Notiz:
Normalerweise wird bei einer Produktionsanwendung ein Protokollsammler eingerichtet, um die Ausgänge der App direkt abzurufen. Es ist daher nicht erforderlich, eine Protokolldatei zu erstellen.
Abschluss
Die Fehlerbehandlung in Python ist ein wichtiger Schritt beim Schreiben von professionellem und zuverlässigem Code. Durch die Kombination von Attempt-Besides-Blöcken, der Erhöhungserklärung und dem endgültigen Block können Sie Fehler vorhersehbar behandeln und gleichzeitig lesbarer und wartbarer Code beibehalten.
Darüber hinaus verbessert ein gutes Protokollierungssystem die Fähigkeit, Ihre Anwendung zu überwachen und zu debuggen. Loguru bietet ein einfaches und flexibles Paket zum Protokollieren von Nachrichten und kann daher einfach in Ihre Codebasis integriert werden.
Zusammenfassend kann die Kombination eines effektiven Fehlerbehebung mit einem umfassenden Protokollierungssystem die Zuverlässigkeit, Wartbarkeit und Debugging -Fähigkeit Ihrer Python -Anwendungen erheblich verbessern.
Referenzen
1 – Fehlerbehandlung in Python: Offizielle Python -Dokumentation zu Ausnahmen
2 – Die Loguru -Dokumentation: https://loguru.readthedocs.io/en/steady/
3 – Leitfaden zu Loguru: https://betterstack.com/group/guides/logging/loguru/