Verwenden von Generatoren für Stocksim - Pipelines

Beginner

This tutorial is from open-source community. Access the source code

Einführung

In diesem Lab lernen Sie, wie Sie Python-Generatoren nutzen können, um effiziente Datenverarbeitungspipelines zu erstellen. Generatoren sind eine leistungsstarke Python-Funktion, die die bedarfsgesteuerte Datenproduktion ermöglicht und somit die Notwendigkeit, alle Daten gleichzeitig im Speicher zu speichern, beseitigt. Sie werden entdecken, wie Sie Generatoren verbinden können, um Datenverarbeitungsworkflows zu erstellen, die Unix-Pipes ähneln.

Die Ziele dieses Labs sind es, die Grundlagen von auf Generatoren basierenden Verarbeitungspipelines zu verstehen, Datenverarbeitungsworkflows mit Python-Generatoren zu erstellen sowie Echtzeit-Datenströme zu filtern und zu formatieren. Die Datei ticker.py wird während dieses Labs erstellt. Beachten Sie, dass für diese Übung das Programm stocksim.py im Hintergrund laufen sollte und Sie die Funktion follow() aus einer früheren Übung verwenden werden.

Grundlegende Generator-Pipeline mit CSV-Daten

In diesem Schritt lernen wir, wie man mit Generatoren eine grundlegende Verarbeitungspipeline erstellt. Zunächst verstehen wir aber, was Generatoren sind. Generatoren sind eine spezielle Art von Iteratoren in Python. Im Gegensatz zu normalen Iteratoren, die möglicherweise alle Daten auf einmal in den Speicher laden, erzeugen Generatoren Werte bedarfsweise. Dies ist äußerst nützlich, wenn es um große Datenströme geht, da es Speicher spart. Anstatt das gesamte Datenset im Speicher zu speichern, erzeugt der Generator die Werte nacheinander, sobald Sie sie benötigen.

Verständnis von Generatoren

Ein Generator ist im Wesentlichen eine Funktion, die einen Iterator zurückgibt. Wenn Sie über diesen Iterator iterieren, erzeugt er eine Sequenz von Werten. Die Schreibweise einer Generatorfunktion ähnelt einer normalen Funktion, aber es gibt einen wichtigen Unterschied. Anstelle der return-Anweisung verwendet eine Generatorfunktion die yield-Anweisung. Die yield-Anweisung hat ein einzigartiges Verhalten. Sie pausiert die Funktion und speichert ihren aktuellen Zustand. Wenn der nächste Wert angefordert wird, setzt die Funktion dort fort, wo sie aufgehört hat. Dies ermöglicht es dem Generator, Werte schrittweise zu erzeugen, ohne jedes Mal von vorne beginnen zu müssen.

Verwendung der follow()-Funktion

Die von Ihnen zuvor erstellte follow()-Funktion funktioniert ähnlich wie der Unix-Befehl tail -f. Der tail -f-Befehl überwacht kontinuierlich eine Datei auf neue Inhalte, und das gleiche macht die follow()-Funktion. Jetzt verwenden wir sie, um eine einfache Verarbeitungspipeline zu erstellen.

Schritt 1: Öffnen eines neuen Terminalfensters

Öffnen Sie zunächst ein neues Terminalfenster in der WebIDE. Dies können Sie tun, indem Sie zu Terminal → New Terminal gehen. In diesem neuen Terminal werden wir unsere Python-Befehle ausführen.

Schritt 2: Starten einer interaktiven Python-Shell

Sobald das neue Terminal geöffnet ist, starten Sie eine interaktive Python-Shell. Dies können Sie tun, indem Sie den folgenden Befehl im Terminal eingeben:

python3

Die interaktive Python-Shell ermöglicht es Ihnen, Python-Code zeilenweise auszuführen und die Ergebnisse sofort zu sehen.

Schritt 3: Importieren der follow-Funktion und Einrichten der Pipeline

Jetzt importieren wir die follow-Funktion und richten eine grundlegende Pipeline ein, um die Aktiendaten zu lesen. Geben Sie in der interaktiven Python-Shell den folgenden Code ein:

>>> from follow import follow
>>> import csv
>>> lines = follow('stocklog.csv')
>>> rows = csv.reader(lines)
>>> for row in rows:
...     print(row)
...

Hier ist, was jede Zeile tut:

  • from follow import follow: Dies importiert die follow-Funktion aus dem follow-Modul.
  • import csv: Dies importiert das csv-Modul, das in Python zum Lesen und Schreiben von CSV-Dateien verwendet wird.
  • lines = follow('stocklog.csv'): Dies ruft die follow-Funktion mit dem Dateinamen stocklog.csv auf. Die follow-Funktion gibt einen Generator zurück, der neue Zeilen liefert, sobald sie zur Datei hinzugefügt werden.
  • rows = csv.reader(lines): Die csv.reader()-Funktion nimmt die von der follow-Funktion erzeugten Zeilen und parst sie in CSV-Datenzeilen.
  • Die for-Schleife iteriert über diese Zeilen und gibt jede Zeile aus.

Schritt 4: Überprüfen der Ausgabe

Nachdem Sie den Code ausgeführt haben, sollten Sie eine Ausgabe ähnlich der folgenden sehen (Ihre Daten werden variieren):

['BA', '98.35', '6/11/2007', '09:41.07', '0.16', '98.25', '98.35', '98.31', '158148']
['AA', '39.63', '6/11/2007', '09:41.07', '-0.03', '39.67', '39.63', '39.31', '270224']
['XOM', '82.45', '6/11/2007', '09:41.07', '-0.23', '82.68', '82.64', '82.41', '748062']
['PG', '62.95', '6/11/2007', '09:41.08', '-0.12', '62.80', '62.97', '62.61', '454327']
...

Diese Ausgabe zeigt, dass Sie erfolgreich eine Datenpipeline erstellt haben. Die follow()-Funktion erzeugt Zeilen aus der Datei, und diese Zeilen werden dann an die csv.reader()-Funktion übergeben, die sie in Datenzeilen parst.

Wenn Sie genug Ausgabe gesehen haben, können Sie die Ausführung durch Drücken von Ctrl+C stoppen.

Was passiert hier?

Lassen Sie uns analysieren, was in dieser Pipeline passiert:

  1. follow('stocklog.csv') erstellt einen Generator. Dieser Generator verfolgt die Datei stocklog.csv und liefert neue Zeilen, sobald sie zur Datei hinzugefügt werden.
  2. csv.reader(lines) nimmt die von der follow-Funktion erzeugten Zeilen und parst sie in CSV-Zeildaten. Sie versteht die Struktur von CSV-Dateien und teilt die Zeilen in einzelne Werte auf.
  3. Die for-Schleife iteriert dann über diese Zeilen und gibt jede Zeile aus. Dies ermöglicht es Ihnen, die Daten in einem lesbaren Format zu sehen.

Dies ist ein einfaches Beispiel für eine Datenverarbeitungspipeline mit Generatoren. In den nächsten Schritten werden wir komplexere und nützlichere Pipelines erstellen.

Erstellen der Ticker-Klasse

Bei der Datenverarbeitung kann die Arbeit mit Rohdaten recht herausfordernd sein. Um unsere Arbeit mit Aktiendaten organisierter und effizienter zu gestalten, definieren wir eine geeignete Klasse, um Aktienkurse darzustellen. Diese Klasse dient als Blaupause für unsere Aktiendaten und macht unsere Datenverarbeitungspipeline robuster und einfacher zu verwalten.

Erstellen der ticker.py-Datei

  1. Zunächst müssen wir eine neue Datei in der WebIDE erstellen. Dies können Sie tun, indem Sie auf das Symbol "New File" klicken oder mit der rechten Maustaste im Dateiexplorer klicken und "New File" auswählen. Benennen Sie diese Datei ticker.py. In dieser Datei wird der Code für unsere Ticker-Klasse gespeichert.

  2. Fügen Sie nun den folgenden Code in Ihre neu erstellte ticker.py-Datei ein. Dieser Code definiert unsere Ticker-Klasse und richtet eine einfache Verarbeitungspipeline ein, um sie zu testen.

## ticker.py

from structure import Structure, String, Float, Integer

class Ticker(Structure):
    name = String()
    price = Float()
    date = String()
    time = String()
    change = Float()
    open = Float()
    high = Float()
    low = Float()
    volume = Integer()

if __name__ == '__main__':
    from follow import follow
    import csv
    lines = follow('stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    for record in records:
        print(record)
  1. Nachdem Sie den Code hinzugefügt haben, speichern Sie die Datei. Dies können Sie tun, indem Sie Strg+S drücken oder im Menü "File" → "Save" auswählen. Das Speichern der Datei stellt sicher, dass Ihre Änderungen gespeichert werden und später ausgeführt werden können.

Verständnis des Codes

Schauen wir uns genauer an, was dieser Code Schritt für Schritt macht:

  1. Am Anfang des Codes importieren wir Structure und Feldtypen aus dem structure.py-Modul. Dieses Modul wurde bereits für Sie eingerichtet. Diese Importe sind wichtig, da sie die Bausteine für unsere Ticker-Klasse bereitstellen. Die Structure-Klasse wird die Basisklasse für unsere Ticker-Klasse sein, und die Feldtypen wie String, Float und Integer werden die Datentypen unserer Aktiendatenfelder definieren.

  2. Als Nächstes definieren wir eine Ticker-Klasse, die von Structure erbt. Diese Klasse hat mehrere Felder, die verschiedene Aspekte der Aktiendaten darstellen:

    • name: Dieses Feld speichert das Aktiensymbol, wie z.B. "IBM" oder "AAPL". Es hilft uns zu identifizieren, für welche Firma wir die Aktien verarbeiten.
    • price: Es enthält den aktuellen Preis der Aktie. Dies ist eine entscheidende Information für Anleger.
    • date und time: Diese Felder geben an, wann der Aktienkurs erstellt wurde. Das Wissen um Zeit und Datum ist wichtig für die Analyse von Aktienkurs-Trends über die Zeit.
    • change: Dies repräsentiert die Preisänderung der Aktie. Es zeigt, ob der Aktienpreis im Vergleich zu einem früheren Zeitpunkt gestiegen oder gefallen ist.
    • open, high, low: Diese Felder repräsentieren den Eröffnungspreis, den höchsten Preis und den niedrigsten Preis der Aktie während eines bestimmten Zeitraums. Sie geben uns eine Vorstellung von der Preisspanne der Aktie.
    • volume: Dieses Feld speichert die Anzahl der gehandelten Aktien. Ein hoher Handelsvolumen kann auf ein starkes Marktinteresse an einer bestimmten Aktie hinweisen.
  3. Im if __name__ == '__main__':-Block richten wir eine Verarbeitungspipeline ein. Dieser Codeblock wird ausgeführt, wenn wir die ticker.py-Datei direkt ausführen.

    • follow('stocklog.csv') ist eine Funktion, die Zeilen aus der stocklog.csv-Datei erzeugt. Sie ermöglicht es uns, die Datei zeilenweise zu lesen.
    • csv.reader(lines) nimmt diese Zeilen und parst sie in Zeildaten. CSV (Comma - Separated Values) ist ein gängiges Dateiformat zum Speichern tabellarischer Daten, und diese Funktion hilft uns, die Daten aus jeder Zeile zu extrahieren.
    • (Ticker.from_row(row) for row in rows) ist ein Generatorausdruck. Er nimmt jede Zeile der Daten und wandelt sie in ein Ticker-Objekt um. Auf diese Weise transformieren we die Roh-CSV-Daten in strukturierte Objekte, mit denen es einfacher zu arbeiten ist.
    • Die for-Schleife iteriert über diese Ticker-Objekte und gibt jedes Objekt aus. Dies ermöglicht es uns, die strukturierten Daten in Aktion zu sehen.

Ausführen des Codes

Lassen Sie uns den Code ausführen, um zu sehen, wie er funktioniert:

  1. Zunächst müssen wir sicherstellen, dass wir im Terminal im Projektverzeichnis sind. Wenn Sie noch nicht dort sind, verwenden Sie den folgenden Befehl, um dorthin zu navigieren:

    cd /home/labex/project
    
  2. Sobald Sie sich im richtigen Verzeichnis befinden, führen Sie das ticker.py-Skript mit dem folgenden Befehl aus:

    python3 ticker.py
    
  3. Nach dem Ausführen des Skripts sollten Sie eine Ausgabe ähnlich der folgenden sehen (Ihre Daten werden variieren):

    Ticker(IBM, 103.53, 6/11/2007, 09:53.59, 0.46, 102.87, 103.53, 102.77, 541633)
    Ticker(MSFT, 30.21, 6/11/2007, 09:54.01, 0.16, 30.05, 30.21, 29.95, 7562516)
    Ticker(AA, 40.01, 6/11/2007, 09:54.01, 0.35, 39.67, 40.15, 39.31, 576619)
    Ticker(T, 40.1, 6/11/2007, 09:54.08, -0.16, 40.2, 40.19, 39.87, 1312959)
    

Sie können die Ausführung des Skripts stoppen, indem Sie Strg+C drücken, wenn Sie genug Ausgabe gesehen haben.

Beachten Sie, wie die Roh-CSV-Daten in strukturierte Ticker-Objekte transformiert wurden. Diese Transformation macht es viel einfacher, mit den Daten in unserer Verarbeitungspipeline zu arbeiten, da wir jetzt die Aktiendaten über die in der Ticker-Klasse definierten Felder zugreifen und manipulieren können.

Aufbau einer komplexeren Datenpipeline

Jetzt werden wir unsere Datenpipeline auf die nächste Stufe heben, indem wir Filterung hinzufügen und die Darstellung der Daten verbessern. Dies wird es einfacher machen, die Informationen, mit denen wir arbeiten, zu analysieren und zu verstehen. Wir werden Änderungen an unserem ticker.py-Skript vornehmen. Die Filterung der Daten hilft uns, uns auf die spezifischen Informationen zu konzentrieren, an denen wir interessiert sind, und die Darstellung in einer schön formatierten Tabelle macht die Daten lesbarer.

Aktualisieren der ticker.py-Datei

  1. Öffnen Sie zunächst Ihre ticker.py-Datei in der WebIDE. Die WebIDE ist ein Tool, das es Ihnen ermöglicht, direkt in Ihrem Browser Code zu schreiben und zu bearbeiten. Sie bietet eine bequeme Umgebung für die Änderung Ihrer Python-Skripte.

  2. Als Nächstes müssen wir den if __name__ == '__main__':-Block in der ticker.py-Datei durch den folgenden Code ersetzen. Dieser Codeblock ist der Einstiegspunkt unseres Skripts, und durch seine Ersetzung ändern wir, wie das Skript die Daten verarbeitet und anzeigt.

if __name__ == '__main__':
    from follow import follow
    import csv
    from tableformat import create_formatter, print_table

    formatter = create_formatter('text')

    lines = follow('stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    negative = (rec for rec in records if rec.change < 0)
    print_table(negative, ['name', 'price', 'change'], formatter)
  1. Nachdem Sie diese Änderungen vorgenommen haben, speichern Sie die Datei. Dies können Sie tun, indem Sie Strg+S auf Ihrer Tastatur drücken oder im Menü "File" → "Save" auswählen. Das Speichern der Datei stellt sicher, dass Ihre Änderungen gespeichert werden und später ausgeführt werden können.

Verständnis der erweiterten Pipeline

Schauen wir uns genauer an, was diese erweiterte Pipeline tut. Das Verständnis jeder Stufe hilft Ihnen zu verstehen, wie die verschiedenen Teile des Codes zusammenarbeiten, um die Daten zu verarbeiten und anzuzeigen.

  1. Wir beginnen damit, create_formatter und print_table aus dem tableformat-Modul zu importieren. Dieses Modul ist bereits für Sie eingerichtet und bietet Funktionen, die uns helfen, die Daten in einer schönen Tabelle zu formatieren und auszugeben.

  2. Dann erstellen wir einen Text-Formatter mit create_formatter('text'). Dieser Formatter wird verwendet, um die Daten auf eine leicht lesbare Weise zu formatieren.

  3. Jetzt zerlegen wir die Pipeline Schritt für Schritt:

    • follow('stocklog.csv') ist eine Funktion, die Zeilen aus der stocklog.csv-Datei erzeugt. Sie überwacht kontinuierlich die Datei auf neue Daten und liefert die Zeilen nacheinander.
    • csv.reader(lines) nimmt die von follow erzeugten Zeilen und parst sie in Zeildaten. Dies ist notwendig, da die Daten in der CSV-Datei in Textform vorliegen und wir sie in ein strukturiertes Format umwandeln müssen, mit dem wir arbeiten können.
    • (Ticker.from_row(row) for row in rows) ist ein Generatorausdruck, der jede Zeile der Daten in ein Ticker-Objekt umwandelt. Ein Ticker-Objekt repräsentiert eine Aktie und enthält Informationen wie den Namen, den Preis und die Änderung der Aktie.
    • (rec for rec in records if rec.change < 0) ist ein weiterer Generatorausdruck, der die Ticker-Objekte filtert. Er behält nur die Objekte, bei denen die Preisänderung der Aktie negativ ist. Dies ermöglicht es uns, uns auf die Aktien zu konzentrieren, deren Preis gefallen ist.
    • print_table(negative, ['name', 'price', 'change'], formatter) nimmt die gefilterten Ticker-Objekte und formatiert sie in eine Tabelle mit dem von uns zuvor erstellten Formatter. Anschließend gibt es die Tabelle in der Konsole aus.

Diese Pipeline zeigt die Stärke von Generatoren. Anstatt alle Daten aus der Datei auf einmal in den Speicher zu laden, verketten wir mehrere Operationen (Lesen, Parsen, Konvertieren, Filtern) und verarbeiten die Daten Stück für Stück. Dies spart Speicher und macht den Code effizienter.

Ausführen der erweiterten Pipeline

Lassen Sie uns den aktualisierten Code ausführen, um die Ergebnisse zu sehen.

  1. Stellen Sie zunächst sicher, dass Sie sich im Terminal im Projektverzeichnis befinden. Wenn Sie noch nicht dort sind, können Sie dorthin navigieren, indem Sie den folgenden Befehl verwenden:

    cd /home/labex/project
    
  2. Sobald Sie sich im Projektverzeichnis befinden, führen Sie das ticker.py-Skript mit dem folgenden Befehl aus:

    python3 ticker.py
    
  3. Nach dem Ausführen des Skripts sollten Sie in der Terminal eine schön formatierte Tabelle sehen. Diese Tabelle zeigt nur die Aktien mit negativen Preisänderungen.

           name      price     change
     ---------- ---------- ----------
              C      53.12      -0.21
            UTX      70.04      -0.19
            AXP      62.86      -0.18
            MMM      85.72      -0.22
            MCD      51.38      -0.03
            WMT      49.85      -0.23
             KO       51.6      -0.07
            AIG      71.39      -0.14
             PG      63.05      -0.02
             HD      37.76      -0.19
    

Wenn Sie genug Ausgabe gesehen haben und die Ausführung des Skripts beenden möchten, können Sie Strg+C auf Ihrer Tastatur drücken.

Die Stärke von Generator-Pipelines

Was wir hier erstellt haben, ist eine leistungsstarke Datenverarbeitungspipeline. Lassen Sie uns zusammenfassen, was sie tut:

  1. Sie überwacht kontinuierlich die stocklog.csv-Datei auf neue Daten. Dies bedeutet, dass die Pipeline automatisch neue Daten verarbeitet, sobald sie zur Datei hinzugefügt werden.
  2. Sie parst die CSV-Daten aus der Datei in strukturierte Ticker-Objekte. Dies erleichtert die Arbeit mit den Daten und die Ausführung von Operationen darauf.
  3. Sie filtert die Daten basierend auf einem bestimmten Kriterium, in diesem Fall negativen Preisänderungen. Dies ermöglicht es uns, uns auf die Aktien zu konzentrieren, die an Wert verlieren.
  4. Sie formatiert und präsentiert die gefilterten Daten in einer lesbaren Tabelle. Dies erleichtert die Analyse der Daten und das Ziehen von Schlussfolgerungen.

Einer der Hauptvorteile der Verwendung von Generatoren in dieser Pipeline ist, dass sie minimalen Speicherplatz benötigt. Generatoren erzeugen Werte bedarfsweise, was bedeutet, dass sie nicht alle Daten auf einmal im Speicher speichern. Dies ähnelt Unix-Pipes, bei denen jede Komponente die Daten verarbeitet und an die nächste Komponente weitergibt.

Sie können sich Generatoren als Lego-Bausteine vorstellen. Genau wie Sie Lego-Bausteine stapeln können, um verschiedene Strukturen zu erstellen, können Sie Generatoren kombinieren, um leistungsstarke Datenverarbeitungsabläufe zu erstellen. Dieser modulare Ansatz ermöglicht es Ihnen, komplexe Systeme aus einfachen, wiederverwendbaren Komponenten aufzubauen.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie Python - Generatoren verwenden können, um effiziente Datenverarbeitungspipelines aufzubauen. Sie haben mehrere wichtige Aufgaben erledigt, wie das Verwenden der follow() - Funktion, um eine Datei auf neue Daten zu überwachen, das Erstellen einer Ticker - Klasse, um Aktienkurse darzustellen, und das Aufbauen einer mehrstufigen Verarbeitungspipeline, die CSV - Daten liest, parst und filtert und dann die Ergebnisse formatiert und anzeigt.

Der auf Generatoren basierte Ansatz bietet mehrere Vorteile, darunter Speichereffizienz, da die Daten bedarfsweise verarbeitet werden, Modularität, die eine einfache Kombination und Wiederverwendung von Pipelinekomponenten ermöglicht, und Einfachheit bei der Darstellung komplexer Datenflüsse. Diese Konzepte werden häufig in der realen Datenverarbeitung angewendet, insbesondere für große Datensätze oder Streaming - Daten.