Verwaltung von Yield-Anweisungen in Python

PythonPythonBeginner
Jetzt üben

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

Einführung

In diesem Lab lernen Sie, wie Sie das Verhalten an yield-Anweisungen in Python steuern können. Sie werden verstehen, wie Sie die mit diesen Anweisungen verbundenen Operationen und Verhaltensweisen effektiv handhaben können.

Darüber hinaus lernen Sie etwas über die Lebensdauer von Generatoren und die Ausnahmebehandlung in Generatoren. Die Dateien follow.py und cofollow.py werden während dieses Lernprozesses modifiziert.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/finally_block("Finally Block") python/AdvancedTopicsGroup -.-> python/generators("Generators") subgraph Lab Skills python/catching_exceptions -.-> lab-132525{{"Verwaltung von Yield-Anweisungen in Python"}} python/finally_block -.-> lab-132525{{"Verwaltung von Yield-Anweisungen in Python"}} python/generators -.-> lab-132525{{"Verwaltung von Yield-Anweisungen in Python"}} end

Verständnis der Lebensdauer und des Schließens von Generatoren

In diesem Schritt werden wir die Lebensdauer von Python-Generatoren untersuchen und lernen, wie wir sie richtig schließen können. Generatoren in Python sind eine spezielle Art von Iteratoren, die es Ihnen ermöglichen, eine Sequenz von Werten on-the-fly zu generieren, anstatt sie alle auf einmal zu berechnen und im Speicher zu speichern. Dies kann sehr nützlich sein, wenn Sie mit großen Datensätzen oder unendlichen Sequenzen arbeiten.

Was ist der follow()-Generator?

Beginnen wir damit, uns die Datei follow.py im Projektverzeichnis anzusehen. Diese Datei enthält eine Generatorfunktion namens follow(). Eine Generatorfunktion wird wie eine normale Funktion definiert, verwendet jedoch statt des Schlüsselworts return das Schlüsselwort yield. Wenn eine Generatorfunktion aufgerufen wird, gibt sie ein Generatorobjekt zurück, über das Sie iterieren können, um die von ihr ausgegebenen Werte zu erhalten.

Die Generatorfunktion follow() liest kontinuierlich Zeilen aus einer Datei und gibt jede gelesene Zeile aus. Dies ähnelt dem Unix-Befehl tail -f, der kontinuierlich eine Datei auf neue Zeilen überwacht.

Öffnen Sie die Datei follow.py im WebIDE-Editor:

import os
import time

def follow(filename):
    with open(filename,'r') as f:
        f.seek(0,os.SEEK_END)
        while True:
            line = f.readline()
            if line == '':
                time.sleep(0.1)    ## Sleep briefly to avoid busy wait
                continue
            yield line

In diesem Code öffnet die Anweisung with open(filename, 'r') as f die Datei im Lese-Modus und stellt sicher, dass sie ordnungsgemäß geschlossen wird, wenn der Block verlassen wird. Die Zeile f.seek(0, os.SEEK_END) bewegt den Dateizeiger an das Ende der Datei, so dass der Generator am Ende beginnt zu lesen. Die Schleife while True liest kontinuierlich Zeilen aus der Datei. Wenn die Zeile leer ist, bedeutet dies, dass es noch keine neuen Zeilen gibt. Daher schläft das Programm für 0,1 Sekunden, um eine Endlosschleife zu vermeiden, und geht dann zur nächsten Iteration über. Wenn die Zeile nicht leer ist, wird sie ausgegeben.

Dieser Generator läuft in einer Endlosschleife, was eine wichtige Frage aufwirft: Was passiert, wenn wir den Generator nicht mehr verwenden oder ihn vorzeitig beenden möchten?

Modifizieren des Generators zur Behandlung des Schließens

Wir müssen die Funktion follow() in follow.py modifizieren, um den Fall zu behandeln, wenn der Generator ordnungsgemäß geschlossen wird. Dazu fügen wir einen try-except-Block hinzu, der die GeneratorExit-Ausnahme fängt. Die GeneratorExit-Ausnahme wird ausgelöst, wenn ein Generator geschlossen wird, entweder durch die Garbage Collection oder durch Aufruf der Methode close().

import os
import time

def follow(filename):
    try:
        with open(filename,'r') as f:
            f.seek(0,os.SEEK_END)
            while True:
                line = f.readline()
                if line == '':
                    time.sleep(0.1)    ## Sleep briefly to avoid busy wait
                    continue
                yield line
    except GeneratorExit:
        print('Following Done')

In diesem modifizierten Code enthält der try-Block die Hauptlogik des Generators. Wenn eine GeneratorExit-Ausnahme ausgelöst wird, fängt der except-Block sie ab und gibt die Nachricht 'Following Done' aus. Dies ist eine einfache Möglichkeit, Aufräumaktionen durchzuführen, wenn der Generator geschlossen wird.

Speichern Sie die Datei nach diesen Änderungen.

Experimentieren mit dem Schließen von Generatoren

Jetzt führen wir einige Experimente durch, um zu sehen, wie Generatoren sich verhalten, wenn sie von der Garbage Collection behandelt oder explizit geschlossen werden.

Öffnen Sie ein Terminal und starten Sie den Python-Interpreter:

cd ~/project
python3

Experiment 1: Garbage Collection eines laufenden Generators

>>> from follow import follow
>>> ## Experiment: Garbage collection of a running generator
>>> f = follow('stocklog.csv')
>>> next(f)
'"MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314\n'
>>> del f  ## Delete the generator object
Following Done  ## This message appears because of our GeneratorExit handler

In diesem Experiment importieren wir zunächst die Funktion follow aus der Datei follow.py. Dann erstellen wir ein Generatorobjekt f durch Aufruf von follow('stocklog.csv'). Wir verwenden die Funktion next(), um die nächste Zeile aus dem Generator zu erhalten. Schließlich löschen wir das Generatorobjekt mit der Anweisung del. Wenn das Generatorobjekt gelöscht wird, wird es automatisch geschlossen, was unseren GeneratorExit-Ausnahmehandler auslöst, und die Nachricht 'Following Done' wird ausgegeben.

Experiment 2: Explizites Schließen eines Generators

>>> f = follow('stocklog.csv')
>>> for line in f:
...     print(line, end='')
...     if 'IBM' in line:
...         f.close()  ## Explicitly close the generator
...
"MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314
"VZ",42.91,"6/11/2007","09:34.28",-0.16,42.95,42.91,42.78,210151
"HPQ",45.76,"6/11/2007","09:34.29",0.06,45.80,45.76,45.59,257169
"GM",31.45,"6/11/2007","09:34.31",0.45,31.00,31.50,31.45,582429
"IBM",102.86,"6/11/2007","09:34.44",-0.21,102.87,102.86,102.77,147550
Following Done
>>> for line in f:
...     print(line, end='')  ## No output: generator is closed
...

In diesem Experiment erstellen wir ein neues Generatorobjekt f und iterieren über es mit einer for-Schleife. Innerhalb der Schleife geben wir jede Zeile aus und prüfen, ob die Zeile die Zeichenkette 'IBM' enthält. Wenn dies der Fall ist, rufen wir die Methode close() auf dem Generator auf, um ihn explizit zu schließen. Wenn der Generator geschlossen wird, wird die GeneratorExit-Ausnahme ausgelöst, und unser Ausnahmehandler gibt die Nachricht 'Following Done' aus. Nachdem der Generator geschlossen wurde, gibt es bei einem erneuten Versuch, über ihn zu iterieren, keine Ausgabe, da der Generator nicht mehr aktiv ist.

Experiment 3: Abbrechen und Fortsetzen eines Generators

>>> f = follow('stocklog.csv')
>>> for line in f:
...     print(line, end='')
...     if 'IBM' in line:
...         break  ## Break out of the loop, but don't close the generator
...
"MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314
"VZ",42.91,"6/11/2007","09:34.28",-0.16,42.95,42.91,42.78,210151
"HPQ",45.76,"6/11/2007","09:34.29",0.06,45.80,45.76,45.59,257169
"GM",31.45,"6/11/2007","09:34.31",0.45,31.00,31.50,31.45,582429
"IBM",102.86,"6/11/2007","09:34.44",-0.21,102.87,102.86,102.77,147550
>>> ## Resume iteration - the generator is still active
>>> for line in f:
...     print(line, end='')
...     if 'IBM' in line:
...         break
...
"CAT",78.36,"6/11/2007","09:37.19",-0.16,78.32,78.36,77.99,237714
"VZ",42.99,"6/11/2007","09:37.20",-0.08,42.95,42.99,42.78,268459
"IBM",102.91,"6/11/2007","09:37.31",-0.16,102.87,102.91,102.77,190859
>>> del f  ## Clean up
Following Done

In diesem Experiment erstellen wir ein Generatorobjekt f und iterieren über es mit einer for-Schleife. Innerhalb der Schleife geben wir jede Zeile aus und prüfen, ob die Zeile die Zeichenkette 'IBM' enthält. Wenn dies der Fall ist, verwenden wir die Anweisung break, um aus der Schleife auszubrechen. Das Ausbrechen aus der Schleife schließt den Generator nicht, so dass der Generator noch aktiv ist. Wir können dann die Iteration fortsetzen, indem wir eine neue for-Schleife über dasselbe Generatorobjekt starten. Schließlich löschen wir das Generatorobjekt, um aufzuräumen, was unseren GeneratorExit-Ausnahmehandler auslöst.

Wichtige Erkenntnisse

  1. Wenn ein Generator geschlossen wird (entweder durch die Garbage Collection oder durch Aufruf von close()), wird innerhalb des Generators eine GeneratorExit-Ausnahme ausgelöst.
  2. Sie können diese Ausnahme fangen, um Aufräumaktionen durchzuführen, wenn der Generator geschlossen wird.
  3. Das Ausbrechen aus der Iteration eines Generators (mit break) schließt den Generator nicht, so dass er später fortgesetzt werden kann.

Beenden Sie den Python-Interpreter, indem Sie exit() eingeben oder Strg+D drücken.

✨ Lösung prüfen und üben

Behandlung von Ausnahmen in Generatoren

In diesem Schritt werden wir lernen, wie man Ausnahmen in Generatoren und Koroutinen behandelt. Zunächst aber verstehen wir, was Ausnahmen sind. Eine Ausnahme ist ein Ereignis, das während der Ausführung eines Programms auftritt und den normalen Ablauf der Programm-Anweisungen unterbricht. In Python können wir die Methode throw() verwenden, um Ausnahmen in Generatoren und Koroutinen zu behandeln.

Verständnis von Koroutinen

Eine Koroutine ist eine spezielle Art von Generator. Im Gegensatz zu normalen Generatoren, die hauptsächlich Werte ausgeben, können Koroutinen sowohl Werte verbrauchen (mit der Methode send()) als auch Werte ausgeben. Die Datei cofollow.py enthält eine einfache Implementierung einer Koroutine.

Öffnen wir die Datei cofollow.py im WebIDE-Editor. Hier ist der Code darin:

def consumer(func):
    def start(*args,**kwargs):
        c = func(*args,**kwargs)
        next(c)
        return c
    return start

@consumer
def printer():
    while True:
        item = yield
        print(item)

Jetzt zerlegen wir diesen Code. Der consumer ist ein Dekorator. Ein Dekorator ist eine Funktion, die eine andere Funktion als Argument nimmt, ihr einige Funktionen hinzufügt und dann die modifizierte Funktion zurückgibt. In diesem Fall bewegt der consumer-Dekorator den Generator automatisch zur ersten yield-Anweisung. Dies ist wichtig, da es den Generator darauf vorbereitet, Werte zu empfangen.

Die Koroutine printer() wird mit dem @consumer-Dekorator definiert. Innerhalb der Funktion printer() haben wir eine unendliche while-Schleife. Die Anweisung item = yield ist der Punkt, an dem die Magie geschieht. Sie pausiert die Ausführung der Koroutine und wartet darauf, einen Wert zu empfangen. Wenn ein Wert an die Koroutine gesendet wird, wird die Ausführung fortgesetzt und der empfangene Wert wird ausgegeben.

Hinzufügen von Ausnahmebehandlung zur Koroutine

Jetzt werden wir die Koroutine printer() modifizieren, um Ausnahmen zu behandeln. Wir werden die Funktion printer() in cofollow.py wie folgt aktualisieren:

@consumer
def printer():
    while True:
        try:
            item = yield
            print(item)
        except Exception as e:
            print('ERROR: %r' % e)

Der try-Block enthält den Code, der eine Ausnahme auslösen könnte. In unserem Fall ist es der Code, der den Wert empfängt und ausgibt. Wenn in dem try-Block eine Ausnahme auftritt, springt die Ausführung zum except-Block. Der except-Block fängt die Ausnahme auf und gibt eine Fehlermeldung aus. Nach diesen Änderungen speichern wir die Datei.

Experimentieren mit Ausnahmebehandlung in Koroutinen

Fangen wir an, zu experimentieren, indem wir Ausnahmen in die Koroutine werfen. Öffnen Sie ein Terminal und starten Sie den Python-Interpreter mit den folgenden Befehlen:

cd ~/project
python3

Experiment 1: Grundlegende Verwendung einer Koroutine

>>> from cofollow import printer
>>> p = printer()
>>> p.send('hello')  ## Send a value to the coroutine
hello
>>> p.send(42)  ## Send another value
42

Hier importieren wir zunächst die Koroutine printer aus dem Modul cofollow. Dann erstellen wir eine Instanz der Koroutine printer namens p. Wir verwenden die Methode send(), um Werte an die Koroutine zu senden. Wie Sie sehen können, verarbeitet die Koroutine die von uns gesendeten Werte ohne Probleme.

Experiment 2: Werfen einer Ausnahme in die Koroutine

>>> p.throw(ValueError('It failed'))  ## Throw an exception into the coroutine
ERROR: ValueError('It failed')

In diesem Experiment verwenden wir die Methode throw(), um eine ValueError-Ausnahme in die Koroutine einzufügen. Der try-except-Block in der Koroutine printer() fängt die Ausnahme auf und gibt eine Fehlermeldung aus. Dies zeigt, dass unsere Ausnahmebehandlung wie erwartet funktioniert.

Experiment 3: Werfen einer echten Ausnahme in die Koroutine

>>> try:
...     int('n/a')  ## This will raise a ValueError
... except ValueError as e:
...     p.throw(e)  ## Throw the caught exception into the coroutine
...
ERROR: ValueError("invalid literal for int() with base 10: 'n/a'")

Hier versuchen wir zunächst, die Zeichenkette 'n/a' in eine Ganzzahl umzuwandeln, was eine ValueError-Ausnahme auslöst. Wir fangen diese Ausnahme auf und verwenden dann die Methode throw(), um sie an die Koroutine zu übergeben. Die Koroutine fängt die Ausnahme auf und gibt die Fehlermeldung aus.

Experiment 4: Überprüfen, dass die Koroutine weiterhin läuft

>>> p.send('still working')  ## The coroutine continues to run after handling exceptions
still working

Nachdem die Ausnahmen behandelt wurden, senden wir einen weiteren Wert an die Koroutine mit der Methode send(). Die Koroutine ist immer noch aktiv und kann den neuen Wert verarbeiten. Dies zeigt, dass unsere Koroutine auch nach dem Auftreten von Fehlern weiterhin laufen kann.

Wichtige Erkenntnisse

  1. Generatoren und Koroutinen können Ausnahmen am Punkt der yield-Anweisung behandeln. Dies bedeutet, dass wir Fehler fangen und behandeln können, die auftreten, wenn die Koroutine auf einen Wert wartet oder ihn verarbeitet.
  2. Die Methode throw() ermöglicht es Ihnen, Ausnahmen in einen Generator oder eine Koroutine einzufügen. Dies ist nützlich für Tests und für die Behandlung von Fehlern, die außerhalb der Koroutine auftreten.
  3. Die richtige Behandlung von Ausnahmen in Generatoren ermöglicht es Ihnen, robuste, fehlertolerante Generatoren zu erstellen, die auch bei Fehlern weiterhin laufen können. Dies macht Ihren Code zuverlässiger und einfacher zu warten.

Um den Python-Interpreter zu beenden, können Sie exit() eingeben oder Strg+D drücken.

✨ Lösung prüfen und üben

Praktische Anwendungen der Generatorverwaltung

In diesem Schritt werden wir untersuchen, wie wir die Konzepte, die wir über die Verwaltung von Generatoren und die Behandlung von Ausnahmen in Generatoren gelernt haben, auf reale Szenarien anwenden können. Das Verständnis dieser praktischen Anwendungen wird Ihnen helfen, robusteres und effizienteres Python-Code zu schreiben.

Erstellen eines robusten Dateiüberwachungssystems

Lassen Sie uns eine zuverlässigere Version unseres Dateiüberwachungssystems erstellen. Dieses System soll in der Lage sein, verschiedene Situationen zu behandeln, wie z. B. Timeouts und Benutzeranforderungen zum Stoppen.

Öffnen Sie zunächst den WebIDE-Editor und erstellen Sie eine neue Datei namens robust_follow.py. Hier ist der Code, den Sie in dieser Datei schreiben müssen:

import os
import time
import signal

class TimeoutError(Exception):
    pass

def timeout_handler(signum, frame):
    raise TimeoutError("Operation timed out")

def follow(filename, timeout=None):
    """
    A generator that yields new lines in a file.
    With timeout handling and proper cleanup.
    """
    try:
        ## Set up timeout if specified
        if timeout:
            signal.signal(signal.SIGALRM, timeout_handler)
            signal.alarm(timeout)

        with open(filename, 'r') as f:
            f.seek(0, os.SEEK_END)
            while True:
                line = f.readline()
                if line == '':
                    ## No new data, wait briefly
                    time.sleep(0.1)
                    continue
                yield line
    except TimeoutError:
        print(f"Following timed out after {timeout} seconds")
    except GeneratorExit:
        print("Following stopped by request")
    finally:
        ## Clean up timeout alarm if it was set
        if timeout:
            signal.alarm(0)
        print("Follow generator cleanup complete")

In diesem Code definieren wir zunächst eine benutzerdefinierte TimeoutError-Klasse. Die Funktion timeout_handler wird verwendet, um diese Fehlermeldung auszulösen, wenn ein Timeout auftritt. Die Funktion follow ist ein Generator, der eine Datei liest und neue Zeilen ausgibt. Wenn ein Timeout angegeben ist, wird ein Alarm mit dem signal-Modul eingerichtet. Wenn es keine neuen Daten in der Datei gibt, wartet es kurz, bevor es es erneut versucht. Der try - except - finally-Block wird verwendet, um verschiedene Ausnahmen zu behandeln und eine ordnungsgemäße Aufräumung sicherzustellen.

Nachdem Sie den Code geschrieben haben, speichern Sie die Datei.

Experimentieren mit dem robusten Dateiüberwachungssystem

Jetzt testen wir unser verbessertes Dateiüberwachungssystem. Öffnen Sie ein Terminal und starten Sie den Python-Interpreter mit den folgenden Befehlen:

cd ~/project
python3

Experiment 1: Grundlegende Verwendung

Im Python-Interpreter testen wir die grundlegende Funktionalität unseres follow-Generators. Hier ist der Code, den Sie ausführen müssen:

>>> from robust_follow import follow
>>> f = follow('stocklog.csv')
>>> for i, line in enumerate(f):
...     print(f"Line {i+1}: {line.strip()}")
...     if i >= 2:  ## Just read a few lines for the example
...         break
...
Line 1: "MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314
Line 2: "VZ",42.91,"6/11/2007","09:34.28",-0.16,42.95,42.91,42.78,210151
Line 3: "HPQ",45.76,"6/11/2007","09:34.29",0.06,45.80,45.76,45.59,257169

Hier importieren wir die Funktion follow aus unserer robust_follow.py-Datei. Dann erstellen wir ein Generatorobjekt f, das die stocklog.csv-Datei überwacht. Wir verwenden eine for-Schleife, um über die vom Generator ausgegebenen Zeilen zu iterieren und die ersten drei Zeilen auszugeben.

Experiment 2: Verwenden des Timeouts

Lassen Sie uns sehen, wie die Timeout-Funktion funktioniert. Führen Sie den folgenden Code im Python-Interpreter aus:

>>> ## Create a generator that will time out after 3 seconds
>>> f = follow('stocklog.csv', timeout=3)
>>> for line in f:
...     print(line.strip())
...     time.sleep(1)  ## Process each line slowly
...
"MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314
"VZ",42.91,"6/11/2007","09:34.28",-0.16,42.95,42.91,42.78,210151
"HPQ",45.76,"6/11/2007","09:34.29",0.06,45.80,45.76,45.59,257169
Following timed out after 3 seconds
Follow generator cleanup complete

In diesem Experiment erstellen wir einen Generator mit einem 3-Sekunden-Timeout. Wir verarbeiten jede Zeile langsam, indem wir zwischen jeder Zeile 1 Sekunde warten. Nach etwa 3 Sekunden löst der Generator eine Timeout-Ausnahme aus, und der Aufräumcode im finally-Block wird ausgeführt.

Experiment 3: Explizites Schließen

Lassen Sie uns testen, wie der Generator ein explizites Schließen behandelt. Führen Sie den folgenden Code aus:

>>> f = follow('stocklog.csv')
>>> for i, line in enumerate(f):
...     print(f"Line {i+1}: {line.strip()}")
...     if i >= 1:
...         print("Explicitly closing the generator...")
...         f.close()
...
Line 1: "MO",70.29,"6/11/2007","09:30.09",-0.01,70.25,70.30,70.29,365314
Line 2: "VZ",42.91,"6/11/2007","09:34.28",-0.16,42.95,42.91,42.78,210151
Explicitly closing the generator...
Following stopped by request
Follow generator cleanup complete

Hier erstellen wir einen Generator und beginnen, über seine Zeilen zu iterieren. Nach der Verarbeitung von zwei Zeilen schließen wir den Generator explizit mit der close-Methode. Der Generator behandelt dann die GeneratorExit-Ausnahme und führt die erforderliche Aufräumung durch.

Erstellen einer Datenverarbeitungspipeline mit Fehlerbehandlung

Als Nächstes erstellen wir eine einfache Datenverarbeitungspipeline mit Koroutinen. Diese Pipeline soll in der Lage sein, Fehler in verschiedenen Stadien zu behandeln.

Öffnen Sie den WebIDE-Editor und erstellen Sie eine neue Datei namens pipeline.py. Hier ist der Code, den Sie in dieser Datei schreiben müssen:

def consumer(func):
    def start(*args,**kwargs):
        c = func(*args,**kwargs)
        next(c)
        return c
    return start

@consumer
def grep(pattern, target):
    """Filter lines containing pattern and send to target"""
    try:
        while True:
            line = yield
            if pattern in line:
                target.send(line)
    except Exception as e:
        target.throw(e)

@consumer
def printer():
    """Print received items"""
    try:
        while True:
            item = yield
            print(f"PRINTER: {item}")
    except Exception as e:
        print(f"PRINTER ERROR: {repr(e)}")

def follow_and_process(filename, pattern):
    """Follow a file and process its contents"""
    import time
    import os

    output = printer()
    filter_pipe = grep(pattern, output)

    try:
        with open(filename, 'r') as f:
            f.seek(0, os.SEEK_END)
            while True:
                line = f.readline()
                if not line:
                    time.sleep(0.1)
                    continue
                filter_pipe.send(line)
    except KeyboardInterrupt:
        print("Processing stopped by user")
    finally:
        filter_pipe.close()
        output.close()

In diesem Code wird der consumer-Dekorator verwendet, um Koroutinen zu initialisieren. Die Koroutine grep filtert Zeilen, die ein bestimmtes Muster enthalten, und sendet sie an eine andere Koroutine. Die Koroutine printer gibt die empfangenen Elemente aus. Die Funktion follow_and_process liest eine Datei, filtert ihre Zeilen mit der grep-Koroutine und gibt die übereinstimmenden Zeilen mit der printer-Koroutine aus. Sie behandelt auch die KeyboardInterrupt-Ausnahme und stellt eine ordnungsgemäße Aufräumung sicher.

Nachdem Sie den Code geschrieben haben, speichern Sie die Datei.

Testen der Datenverarbeitungspipeline

Lassen Sie uns unsere Datenverarbeitungspipeline testen. Führen Sie in einem Terminal den folgenden Befehl aus:

cd ~/project
python3 -c "from pipeline import follow_and_process; follow_and_process('stocklog.csv', 'IBM')"

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

PRINTER: "IBM",102.86,"6/11/2007","09:34.44",-0.21,102.87,102.86,102.77,147550

PRINTER: "IBM",102.91,"6/11/2007","09:37.31",-0.16,102.87,102.91,102.77,190859

PRINTER: "IBM",102.95,"6/11/2007","09:39.44",-0.12,102.87,102.95,102.77,225350

Diese Ausgabe zeigt, dass die Pipeline korrekt funktioniert und Zeilen filtert und ausgibt, die das "IBM"-Muster enthalten.

Um den Prozess zu stoppen, drücken Sie Strg+C. Sie sollten die folgende Nachricht sehen:

Processing stopped by user

Wichtige Erkenntnisse

  1. Die richtige Behandlung von Ausnahmen in Generatoren ermöglicht es Ihnen, robuste Systeme zu erstellen, die Fehler gracefully behandeln können. Dies bedeutet, dass Ihre Programme nicht unerwartet abstürzen, wenn etwas schief geht.
  2. Sie können Techniken wie Timeouts verwenden, um zu verhindern, dass Generatoren unendlich laufen. Dies hilft, Systemressourcen zu verwalten und stellt sicher, dass Ihr Programm nicht in einer Endlosschleife hängen bleibt.
  3. Generatoren und Koroutinen können leistungsstarke Datenverarbeitungspipelines bilden, in denen Fehler propagiert und auf der entsprechenden Ebene behandelt werden können. Dies erleichtert es, komplexe Datenverarbeitungssysteme zu erstellen.
  4. Der finally-Block in Generatoren stellt sicher, dass Aufräumoperationen ausgeführt werden, unabhängig davon, wie der Generator beendet wird. Dies hilft, die Integrität Ihres Programms aufrechtzuerhalten und verhindert Ressourcenlecks.
✨ Lösung prüfen und üben

Zusammenfassung

In diesem Lab haben Sie essentielle Techniken zum Verwalten von yield-Anweisungen in Python-Generatoren und -Koroutinen gelernt. Sie haben die Verwaltung der Lebensdauer von Generatoren untersucht, einschließlich der Behandlung der GeneratorExit-Ausnahme beim Schließen oder der Garbage Collection sowie der Kontrolle des Iterationsabbruchs und -fortsetzens. Darüber hinaus haben Sie die Ausnahmebehandlung in Generatoren kennengelernt, wie z. B. die Verwendung der throw()-Methode und das Schreiben robuster Generatoren, um Ausnahmen gracefully zu behandeln.

Diese Techniken sind grundlegend für das Bauen robuster und wartbarer Python-Anwendungen. Sie sind nützlich für die Datenverarbeitung, asynchrone Operationen und die Ressourcenverwaltung. Durch die richtige Verwaltung der Lebensdauer von Generatoren und die Behandlung von Ausnahmen können Sie widerstandsfähige Systeme erstellen, die Fehler gracefully behandeln und Ressourcen aufräumen, wenn sie nicht mehr benötigt werden.