ist jetzt verfügbar! Lesen Sie über die neuen Funktionen und Fehlerbehebungen vom November.

FastAPI-Tutorial in Visual Studio Code

FastAPI ist ein modernes, hochperformantes Webframework zum Erstellen von APIs mit Python. Es wurde entwickelt, um das schnelle und effiziente Erstellen von APIs zu vereinfachen und bietet Funktionen wie automatische Validierung, Serialisierung und Dokumentation Ihrer API, was es zu einer beliebten Wahl für die Erstellung von Webdiensten und Microservices macht.

In diesem FastAPI-Tutorial erstellen wir eine Einkaufslisten-App mit FastAPI. Am Ende des Tutorials verstehen Sie, wie Sie mit FastAPI im Visual Studio Code-Terminal, Editor und Debugger arbeiten. Dieses Tutorial ist keine tiefgehende Einführung in FastAPI. Dafür können Sie sich auf die offizielle FastAPI-Dokumentation beziehen.

Wenn Sie Python zum ersten Mal verwenden, empfehlen wir Ihnen, mit unserem Python-Tutorial zu beginnen, um sich mit der Sprache und der Python-Unterstützung von VS Code vertraut zu machen. Dieses Tutorial eignet sich eher für diejenigen, die bereits mit Python vertraut sind und lernen möchten, wie sie mit FastAPI in VS Code arbeiten.

Das abgeschlossene Code-Projekt aus diesem FastAPI-Tutorial finden Sie auf GitHub: python-sample-vscode-fastapi-tutorial.

Wenn Sie Probleme haben, können Sie auf den Diskussionen zur Python-Erweiterung (Fragen & Antworten) nach Antworten suchen oder eine Frage stellen.

Projekt einrichten

Es gibt verschiedene Möglichkeiten, Ihr Projekt für dieses Tutorial einzurichten. Wir behandeln, wie Sie es in GitHub Codespaces und in VS Code auf Ihrem lokalen Rechner einrichten können.

GitHub Codespaces

Sie können dieses Projekt so einrichten, dass Sie in GitHub Codespaces entwickeln können, wo Sie Ihre App remote in einem Codespace codieren, debuggen und ausführen können. Ein Codespace bietet eine vollständig konfigurierte Entwicklungsumgebung, die in der Cloud gehostet wird und den Bedarf an lokaler Einrichtung überflüssig macht. Diese Umgebung umfasst die Abhängigkeiten, Tools und Erweiterungen Ihres Projekts und gewährleistet eine konsistente und reproduzierbare Entwicklungserfahrung. Sie optimiert die Zusammenarbeit, indem sie Echtzeitbearbeitung, integrierte Versionskontrolle und einfachen Zugriff auf Debugging- und Testwerkzeuge bietet und gleichzeitig die Sicherheit und Zuverlässigkeit Ihres Projekts aufrechterhält.

Hinweis: Alle GitHub.com-Konten verfügen über eine monatliche Freikontingent für die Nutzung von GitHub Codespaces, die in den kostenlosen oder Pro-Plänen enthalten ist. Weitere Informationen finden Sie unter Informationen zur Abrechnung für GitHub Codespaces.

Um einen Codespace für dieses Tutorial einzurichten, navigieren Sie zum GitHub-Repository dieses Projekts. Dieser Codespace enthält alle notwendigen Konfigurationen und Abhängigkeiten, um schnell mit der FastAPI-Entwicklung zu beginnen.

Wählen Sie für dieses Tutorial den Branch dictionarybased

dictionarybased branch selected in the python-sample-vscode-fastapi-tutorial GitHub repo

Wählen Sie dann Code > Codespaces > Codespace auf dem Branch <dictionarybased> erstellen, um einen Codespace für Ihr Projekt zu erstellen und zu öffnen.

Wenn Sie fertig sind, können Sie mit dem Abschnitt Die Datenbank ersetzen unten fortfahren.

Lokal in VS Code

Um dieses Tutorial in VS Code erfolgreich abzuschließen, müssen Sie zunächst Ihre Python-Entwicklungsumgebung einrichten. Insbesondere erfordert dieses Tutorial

In diesem Abschnitt erstellen wir einen Ordner, den wir als Arbeitsbereich in VS Code öffnen, richten eine Python-virtuelle Umgebung ein und installieren die Abhängigkeiten des Projekts.

  1. Erstellen Sie in Ihrem Dateisystem einen Projektordner für dieses Tutorial, z. B. groceries-plugin.

  2. Öffnen Sie diesen neuen Ordner in VS Code (Datei > Ordner öffnen…).

  3. Wenn die Aufforderung Workspace Trust angezeigt wird, wählen Sie Ja, ich vertraue den Autoren, um dem Workspace den Zugriff auf notwendige Ressourcen und Erweiterungen zu gestatten. Weitere Informationen zu Workspace Trust finden Sie in der Dokumentation.

Erstellen wir nun eine Datei requirements.txt, die die Abhängigkeiten auflistet, die wir für die Anwendung installieren möchten. Die Datei requirements.txt ist eine gängige Praxis in der Python-Entwicklung, um die Bibliotheken anzugeben, von denen Ihr Projekt abhängt, sowie deren Versionen. Diese Datei hilft sicherzustellen, dass jeder, der an dem Projekt arbeitet, eine ähnliche Entwicklungsumgebung erstellen kann, was sie zu einer praktischen Komponente für die Aufrechterhaltung der Konsistenz macht.

Wir installieren FastAPI zum Erstellen der App, uvicorn als Server und Redis sowie type-redis für die Datenhaltung und die Interaktion mit einer Redis-Datenbank.

  1. Erstellen Sie eine neue Datei in VS Code (Datei > Neue Textdatei oder ⌘N (Windows, Linux Ctrl+N)).

  2. Fügen Sie den folgenden Inhalt hinzu

    fastapi
    redis
    types-redis
    uvicorn
    
  3. Speichern Sie die Datei (⌘S (Windows, Linux Ctrl+S)) und nennen Sie sie requirements.txt.

  4. Erstellen Sie eine virtuelle Umgebung, indem Sie die Befehlspalette öffnen (⇧⌘P (Windows, Linux Ctrl+Shift+P)) und den Befehl Python: Environment erstellen ausführen.

    Hinweis: Dieser Schritt kann einige Minuten dauern.

  5. Wählen Sie bei der Aufforderung nach dem Umgebungstyp Venv

    Dropdown with "Venv" or "Conda" as options for environments that can be created with the Python: Create Environment command

  6. Wählen Sie dann die neueste Python-Version aus, die auf Ihrem Rechner verfügbar ist

    List of available global environments that can be used to create a virtual environment

  7. Wählen Sie die Datei requirements.txt aus der Dropdown-Liste aus, damit die Abhängigkeiten automatisch installiert werden, und wählen Sie dann OK

    Check box selected to install dependencies from requirements.txt file

Die virtuelle Umgebung wird erstellt, die Abhängigkeiten werden automatisch installiert und die Umgebung wird für Ihren Arbeitsbereich ausgewählt, die von der Python-Erweiterung verwendet werden soll. Sie können dies bestätigen, indem Sie die rechte untere Ecke von VS Code überprüfen

Environment in the Status bar

Hinweis: Wenn Sie die neu erstellte Umgebungsinformation nicht in der Statusleiste finden, können Sie auf die Anzeige des Python-Interpreters klicken (oder den Befehl Python: Interpreter auswählen aus der Befehlspalette ausführen) und die virtuelle Umgebung manuell auswählen.

Mit dem Codieren beginnen

Lassen Sie uns die Anwendung erstellen!

  1. Erstellen Sie eine neue Python-Datei mit Datei > Neue Datei… und wählen Sie dann Python-Datei.

  2. Speichern Sie sie im Ordner groceries-plugin als main.py (⇧⌘S (Windows, Linux Ctrl+Shift+S)).

  3. Fügen Sie den folgenden Code zu main.py hinzu und speichern Sie die Datei

    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.get("/")
    def root():
        return {"message": "Hello World"}
    
  4. Führen Sie den Code aus, indem Sie den Debugger starten (F5).

  5. Wählen Sie aus dem Dropdown-Menü die Konfigurationsoption FastAPI aus der Liste

    Dropdown with debugger configuration options, with FastAPI being highlighted

    Dies erstellt automatisch eine Debug-Konfiguration, die uvicorn aufruft, um den Anwendungsserver über den Debugger zu starten, und es Ihnen ermöglicht, den Quellcode schrittweise zu durchlaufen, um sein Verhalten zu untersuchen. Sie sollten etwas Ähnliches wie das Folgende im Terminal sehen

    Uvicorn server running message displayed in the terminal, with an URL to access the app

    Tipp: Wenn Ihr Standardport bereits belegt ist, stoppen Sie den Debugger, öffnen Sie die Befehlspalette (⇧⌘P (Windows, Linux Ctrl+Shift+P)), suchen Sie nach Debug: Konfiguration hinzufügen, wählen Sie Python Debugger, und dann FastAPI. Dies erstellt eine benutzerdefinierte Konfigurationsdatei im Verzeichnis .vscode/launch.json, die Sie bearbeiten können. Fügen Sie Folgendes zu "args":[] hinzu, um einen benutzerdefinierten Port festzulegen: "--port=5000". Speichern Sie die Datei und starten Sie den Debugger neu mit (F5).

  6. Ctrl+Klick auf die URL http://127.0.0.1:8000/ im Terminal, um Ihren Standardbrowser zu dieser Adresse zu öffnen

    Hello World message displayed in the browser

    Herzlichen Glückwunsch! Ihre FastAPI-App läuft!

  7. Stoppen Sie den Debugger mit der Schaltfläche Stoppen in der Debug-Symbolleiste oder über ⇧F5 (Windows, Linux Shift+F5).

Ein Modell für Einkaufslistenartikel erstellen

Nachdem die FastAPI-App nun funktioniert, können wir unsere Einkaufslistenartikel mit Pydantic definieren, einer Datenvalidierungs- und Parsing-Bibliothek, die sich nahtlos in FastAPI integriert. Pydantic ermöglicht es Ihnen, Datenmodelle mithilfe von Python-Klassen mit Type Hints zu definieren, um eingehende Daten (sogenannte "Payloads") in API-Anfragen automatisch zu validieren und zu parsen.

Erstellen wir ein Modell für unsere Einkaufslistenartikel. Wir verwenden das Modell ItemPayload, um die Datenstruktur der Artikel zu definieren, die zur Einkaufsliste hinzugefügt werden sollen. Dieses Modell hat drei Felder: item_id, item_name und quantity.

  1. Erstellen Sie eine neue Python-Datei mit Datei > Neue Datei… und wählen Sie dann Python-Datei.

  2. Fügen Sie die folgenden Zeilen in die Datei ein und speichern Sie sie dann im Ordner groceries-plugin als models.py (⇧⌘S (Windows, Linux Ctrl+Shift+S))

    from typing import Optional
    from pydantic import BaseModel
    
    class ItemPayload(BaseModel):
        item_id: Optional[int]
        item_name: str
        quantity: int
    

Pylance, der Standard-Sprachserver für Python in VS Code, unterstützt Type-Hinting-Funktionen, die beim Arbeiten mit Pydantic-Modellen und FastAPI hilfreich sein können. Dies liegt daran, dass Pylance auf Pyright basiert, einem statischen Typchecker für Python, der Typfehler in Ihrem Code erkennen kann, um Fehler zu vermeiden und die Codequalität zu verbessern.

Die folgenden drei Schritte sind optional, aber da FastAPI intensiv Type Hints verwendet, um die Lesbarkeit und Validierung des Codes zu verbessern, können wir die Type-Checking-Funktionen von Pylance nutzen, um Fehler frühzeitig zu erkennen.

  1. Öffnen Sie den Einstellungen-Editor (⌘, (Windows, Linux Ctrl+,)).

  2. Suchen Sie nach "python type checking mode" und stellen Sie ihn auf basic für grundlegendes Type Checking. Pylance zeigt nun Diagnosen und Warnungen an, um einfache typbezogene Fehler zu erkennen. Alternativ können Sie ihn auf strict setzen, um erweiterte Type-Checking-Regeln durchzusetzen.

    Python Analysis Type Checking Mode options (off, basic and strict) in Settings editor

  3. Suchen Sie als Nächstes nach "Python inlay type hints" und aktivieren Sie Inline-Hinweise für Variablentypen und Funktionsrückgabetypen

    Two Python Analysis Type Hints settings being enabled in the Settings editor: for Function Return Types and for Variable Types

Routen erstellen

Nun benötigen wir einen Ort, um die Einkaufslistenartikel zu speichern. Der Einfachheit halber beginnen wir mit einem leeren Dictionary.

  1. Ersetzen Sie zuerst die erste Importzeile in der Datei main.py durch die folgenden Zeilen, um alle benötigten Pakete für das Beispiel zu importieren

    from fastapi import FastAPI, HTTPException
    
    from models import ItemPayload
    
  2. Fügen Sie nun die folgende Zeile direkt unter app = FastAPI() hinzu

    grocery_list: dict[int, ItemPayload] = {}
    

    Dies erstellt ein neues leeres Dictionary, das Schlüssel vom Typ int (als Artikel-IDs) und Werte vom Typ ItemPayload empfängt.

    Wir definieren nun Routen in unserer FastAPI-Anwendung. Im Kontext von Webanwendungen sind Routen wie Pfade, die bestimmte URLs dem Code zuordnen, der sie verarbeitet. Diese Routen dienen als Einstiegspunkte für die verschiedenen Funktionalitäten innerhalb unserer Anwendung. Wenn ein Client, wie z. B. ein Webbrowser oder ein anderes Programm, eine Anfrage an unsere Anwendung mit einer bestimmten URL sendet, leitet FastAPI diese Anfrage basierend auf der URL an die entsprechende Funktion (auch bekannt als Routenhandler oder View-Funktion) weiter, und diese Funktion verarbeitet die Anfrage und generiert eine Antwort.

    Lassen Sie uns mit der Definition von Routen zum Hinzufügen und Abrufen einzelner Artikel sowie zum Zurückgeben aller Artikel in der Einkaufsliste fortfahren.

  3. Fügen Sie die folgende Route am Ende der Datei main.py hinzu

    # Route to add a item
    @app.post("/items/{item_name}/{quantity}")
    def add_item(item_name: str, quantity: int):
        if quantity <= 0:
            raise HTTPException(status_code=400, detail="Quantity must be greater than 0.")
        # if item already exists, we'll just add the quantity.
        # get all item names
        items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()}
        if item_name in items_ids.keys():
            # get index of item_name in item_ids, which is the item_id
            item_id = items_ids[item_name]
            grocery_list[item_id].quantity += quantity
    # otherwise, create a new item
        else:
            # generate an ID for the item based on the highest ID in the grocery_list
            item_id = max(grocery_list.keys()) + 1 if grocery_list else 0
            grocery_list[item_id] = ItemPayload(
                item_id=item_id, item_name=item_name, quantity=quantity
            )
    
        return {"item": grocery_list[item_id]}
    

    Wenn Sie Type Hints im vorherigen Abschnitt aktiviert haben, stellen Sie fest, dass Pylance Inline-Hinweise mit dem Rückgabetyp der Funktion sowie den Typen für item_ids und item_id hinzufügt. Sie können optional auf jeden Vorschlag doppelklicken, um ihn in den Code einzufügen

    Inlay function return and variable type hints being displayed by Pylance throughout the sample code

    Lassen Sie uns nun prüfen, ob diese Route wie erwartet funktioniert. Der schnellste Weg dazu ist die Nutzung sowohl des Debuggers von VS Code als auch des /docs-Endpunkts von FastAPI, der Informationen über alle verfügbaren API-Routen liefert und es Ihnen ermöglicht, mit der API zu interagieren, um ihre Parameter und Antworten zu erkunden. Diese Dokumentation wird dynamisch basierend auf den Metadaten und Type Hints, die in der FastAPI-Anwendung definiert sind, generiert.

  4. Setzen Sie einen Haltepunkt neben der Anweisung if quantity <= 0, indem Sie auf den linken Rand der Zeilennummer klicken (oder auf F9). Der Debugger stoppt vor der Ausführung dieser Zeile, sodass Sie den Code Zeile für Zeile untersuchen können.

    Breakpoint set next to the first line in the add_item function

  5. Starten Sie den Debugger (F5) und navigieren Sie dann im Browser zu http://127.0.0.1:8000/docs.

    Es sollte eine Swagger-Oberfläche mit den beiden verfügbaren Endpunkten in der App vorhanden sein: /items und der Root (/).

    Swagger UI displaying two endpoints: /items and /

  6. Wählen Sie den Pfeil nach unten neben der Route /items aus, um sie zu erweitern, und dann die Schaltfläche Try it out, die auf der rechten Seite erscheint.

    "Try it out" button displayed next to the /items route in the Swagger UI

  7. Fügen Sie einen Einkaufslistenartikel hinzu, indem Sie einen String für das Feld item_name und eine Zahl für quantity übergeben. Sie könnten zum Beispiel 'apple' als item_name und 2 als quantity angeben.

  8. Wählen Sie Execute.

    Execute button displayed below the /items route

  9. Öffnen Sie VS Code erneut und stellen Sie fest, dass der Debugger am zuvor gesetzten Haltepunkt angehalten hat.

    Debugger stopped at the breakpoint set in the add_item function

    Auf der linken Seite werden alle lokalen und globalen Variablen, die zu diesem Zeitpunkt definiert sind, im Fenster Variablen unter der Ansicht Ausführen und Debuggen angezeigt. In unserem Beispiel ist item_name auf 'apple' und quantity auf 2 unter der lokalen Variablenansicht eingestellt, sowie ein leeres grocery_list-Dictionary unter der globalen Variablenansicht.

    Variables window displayed in the Run and Debug view, with the item and grocery_list variables highlighted

    Lassen Sie uns nun die Debug-Konsole von VS Code zur Erkundung nutzen.

  10. Wählen Sie die Anweisung quantity <= 0 aus, klicken Sie mit der rechten Maustaste auf den Editor und wählen Sie Im Debug-Konsolen auswerten

    Evaluate in Debug Console option displayed in the context menu when right-clicking on a line of code

    Dies öffnet die Debug-Konsole und führt den ausgewählten Ausdruck aus. Wie in unserem Beispiel erwartet, wird der Ausdruck zu False ausgewertet.

    Die Debug-Konsole kann ein mächtiges Werkzeug sein, um schnell Ausdrücke zu testen und den Zustand Ihres Codes zum Zeitpunkt eines Haltepunkts besser zu verstehen. Sie können sie auch verwenden, um beliebigen Code auszuführen, z. B. Funktionen aufzurufen oder Variablen auszugeben. Weitere Informationen zum Debuggen von Python in VS Code finden Sie im Python-Tutorial.

    Sie können die Ausführung des Codes jetzt fortsetzen, indem Sie auf Weiter in der Symbolleiste der Debug-Ansicht klicken oder F5 drücken.

    Fügen wir abschließend die restlichen Routen für die Anwendung hinzu, damit wir alle Artikel oder bestimmte Artikel auflisten und sie aus unserer Einkaufsliste entfernen können. Sie können den Debugger weiterlaufen lassen, da die Anwendung automatisch neu geladen wird, wenn Sie die Änderungen im nächsten Schritt speichern.

  11. Ersetzen Sie den Inhalt in main.py durch den folgenden Code

    from fastapi import FastAPI, HTTPException
    
    from models import ItemPayload
    
    app = FastAPI()
    
    grocery_list: dict[int, ItemPayload] = {}
    
    # Route to add an item
    @app.post("/items/{item_name}/{quantity}")
    def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]:
        if quantity <= 0:
            raise HTTPException(status_code=400, detail="Quantity must be greater than 0.")
        # if item already exists, we'll just add the quantity.
        # get all item names
        items_ids: dict[str, int] = {
            item.item_name: item.item_id if item.item_id is not None else 0
            for item in grocery_list.values()
        }
        if item_name in items_ids.keys():
            # get index of item_name in item_ids, which is the item_id
            item_id: int = items_ids[item_name]
            grocery_list[item_id].quantity += quantity
        # otherwise, create a new item
        else:
            # generate an ID for the item based on the highest ID in the grocery_list
            item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0
            grocery_list[item_id] = ItemPayload(
                item_id=item_id, item_name=item_name, quantity=quantity
            )
    
        return {"item": grocery_list[item_id]}
    
    
    # Route to list a specific item by ID
    @app.get("/items/{item_id}")
    def list_item(item_id: int) -> dict[str, ItemPayload]:
        if item_id not in grocery_list:
            raise HTTPException(status_code=404, detail="Item not found.")
        return {"item": grocery_list[item_id]}
    
    
    # Route to list all items
    @app.get("/items")
    def list_items() -> dict[str, dict[int, ItemPayload]]:
        return {"items": grocery_list}
    
    
    # Route to delete a specific item by ID
    @app.delete("/items/{item_id}")
    def delete_item(item_id: int) -> dict[str, str]:
        if item_id not in grocery_list:
            raise HTTPException(status_code=404, detail="Item not found.")
        del grocery_list[item_id]
        return {"result": "Item deleted."}
    
    
    # Route to remove some quantity of a specific item by ID
    @app.delete("/items/{item_id}/{quantity}")
    def remove_quantity(item_id: int, quantity: int) -> dict[str, str]:
        if item_id not in grocery_list:
            raise HTTPException(status_code=404, detail="Item not found.")
        # if quantity to be removed is higher or equal to item's quantity, delete the item
        if grocery_list[item_id].quantity <= quantity:
            del grocery_list[item_id]
            return {"result": "Item deleted."}
        else:
            grocery_list[item_id].quantity -= quantity
        return {"result": f"{quantity} items removed."}
    
    
  12. Speichern Sie die Datei (⌘S (Windows, Linux Ctrl+S)). Die Anwendung sollte automatisch neu geladen werden.

Sie können nun erneut die Seite /docs öffnen und die neuen Routen testen, indem Sie den Debugger und die Debug-Konsole verwenden, um die Codeausführung besser zu verstehen. Wenn Sie fertig sind, können Sie den Debugger stoppen (⇧F5 (Windows, Linux Shift+F5)). Sie können auch den Haltepunkt entfernen, den wir in Schritt 4 hinzugefügt haben, indem Sie darauf klicken.

Herzlichen Glückwunsch! Sie haben nun eine funktionierende FastAPI-Anwendung mit Routen zum Hinzufügen, Auflisten und Löschen von Artikeln aus einer Einkaufsliste.

Datenspeicherung einrichten

An diesem Punkt haben Sie bereits eine funktionierende Version der Anwendung mit der Grundfunktionalität. Dieser Abschnitt führt Sie durch die Einrichtung der Datenspeicherung für die Persistenz, aber Sie können ihn überspringen, wenn Sie mit dem bisher Gelernten zufrieden sind.

Bisher speichern wir die Daten in einem Dictionary, was nicht ideal ist, da alle Daten verloren gehen, wenn die Anwendung neu gestartet wird.

Um die Daten zu persistent zu machen, werden wir Redis verwenden, einen Open-Source-In-Memory-Datenspeicher. Aufgrund seiner Geschwindigkeit und Vielseitigkeit wird Redis häufig als Datenspeichersystem in einer Vielzahl von Anwendungen verwendet, darunter Webanwendungen, Echtzeit-Analyse-Systeme, Caching-Schichten, dieses Tutorial und mehr.

Wenn Sie bereits mit GitHub Codespaces mit unserer bestehenden Vorlage arbeiten, können Sie direkt zum Abschnitt Die Datenbank ersetzen springen.

Wenn Sie unter Windows arbeiten, können Sie mit Redis arbeiten, indem Sie entweder einen Docker-Container oder einen GitHub Codespace einrichten. In diesem Tutorial verwenden wir einen Docker-Container, aber Sie können sich auf den obigen Abschnitt für Anleitungen zur Einrichtung eines GitHub Codespace beziehen.

Wenn Sie sich auf einer Linux- oder macOS-Maschine befinden, können Sie Redis installieren, indem Sie die Anweisungen auf deren Website befolgen und dann zum Abschnitt Die Datenbank ersetzen springen.

Einrichtung eines Docker-Containers unter Windows

Die VS Code-Erweiterung Dev Containers bietet einen optimierten Ansatz, um Ihr Projekt, seine Abhängigkeiten und alle notwendigen Werkzeuge in einem einzigen Container zu konsolidieren und so eine voll funktionsfähige Entwicklungsumgebung zu schaffen. Die Erweiterung ermöglicht es Ihnen, Ihr Projekt innerhalb (oder in den Container gemountet) des Containers in VS Code zu öffnen, wo Sie dessen vollen Funktionsumfang nutzen können.

Stellen Sie für die folgenden Schritte sicher, dass Sie die folgenden Anforderungen auf Ihrem Rechner installiert haben

Voraussetzungen

Dev-Container-Konfiguration erstellen

  1. Öffnen Sie die Befehlspalette und führen Sie Dev Containers: Dev Container-Konfigurationsdateien hinzufügen… aus.

  2. Wählen Sie Python 3

    Python 3 option selected in the Dev Containers configuration files list

  3. Wählen Sie die Standardversion.

  4. Wählen Sie Redis Server als zusätzliche zu installierende Funktion, drücken Sie OK und wählen Sie dann Standardwerte beibehalten.

    Wir können optional Features installieren, die in den Container aufgenommen werden sollen. Für dieses Tutorial installieren wir Redis Server, ein von der Community beigesteuertes Feature, das die richtige Dev-Container-Einrichtung für Redis installiert und hinzufügt.

    Redis Server option selected in the Dev Containers configuration files list

    Dies erstellt einen Ordner .devcontainer in Ihrem Arbeitsbereich mit einer Datei devcontainer.json. Nehmen wir einige Änderungen an dieser Datei vor, damit die Container-Einrichtung Schritte wie die Installation der benötigten VS Code-Erweiterungen sowie der Projekt Abhängigkeiten umfasst.

  5. Öffnen Sie die Datei devcontainer.json.

  6. Fügen Sie nach dem Eintrag "features" : { ... } ein "," hinzu, damit wir weitere Einstellungen zur Datei hinzufügen können.

    Als Nächstes fügen wir die notwendigen Befehle zur Installation von Abhängigkeiten in die Eigenschaft postCreateCommand in der Datei devcontainer.json ein, damit unsere Anwendung nach der Einrichtung des Containers bereit zur Ausführung ist.

  7. Suchen Sie den folgenden Inhalt und entfernen Sie den Kommentar (//) von dieser Zeile, damit die Abhängigkeiten nach der Erstellung des Containers installiert werden können

    "postCreateCommand": "pip3 install --user -r requirements.txt",
    

    Sie können mehr über postCreateCommand und weitere Lifecycle-Skripte in der Development Containers Specification erfahren.

    Nun verwenden wir die Eigenschaft customizations, um die VS Code-Erweiterungen hinzuzufügen, die wir im Container installiert haben möchten.

  8. Fügen Sie die folgende Einstellung zu devcontainer.json hinzu

        // Use 'postCreateCommand' to run commands after the container is created.
        "postCreateCommand": "pip3 install --user -r requirements.txt",
    
        // Configure tool-specific properties.
        "customizations": {
            "vscode": {
                "extensions": [
                    "ms-python.python", //Python extension ID
                    "ms-python.vscode-pylance" //Pylance extension ID
                ]
            }
        }
    
  9. Speichern Sie die Datei.

  10. Wählen Sie Im Container neu öffnen aus der Benachrichtigung, die in der rechten unteren Ecke angezeigt wird, oder führen Sie den Befehl Dev Containers: Im Container neu öffnen aus der Befehlspalette aus.

    Hinweis: Es kann mehrere Minuten dauern, bis der Container erstellt ist, abhängig von der Internetgeschwindigkeit und der Leistung des Rechners.

    Sie können mehr über die Dev-Container-Konfiguration in der Dev Containers-Dokumentation erfahren.

Sobald dies abgeschlossen ist, haben Sie einen voll konfigurierten Linux-basierten Arbeitsbereich mit Python 3 und Redis Server installiert.

Sobald der Container eingerichtet ist, sehen Sie eine Anzeige in der linken unteren Ecke von VS Code

Dev Containers indicator displayed on the bottom left corner of VS Code

Hinweis: Stellen Sie sicher, dass die Python- und Pylance-Erweiterungen im Container erfolgreich installiert wurden, indem Sie die Erweiterungsansicht öffnen (⇧⌘X (Windows, Linux Ctrl+Shift+X)) und danach suchen. Wenn nicht, können Sie sie installieren, indem Sie Im Dev-Container installieren ausführen.

Die ausgewählten Informationen zum Python-Interpreter sind in der Statusleiste unten rechts verfügbar und entsprechen der in der Datei devcontainer.json angegebenen Version.

Python interpreter selection

Hinweis: Wenn Sie die Informationen zum Python-Interpreter nicht in der Statusleiste finden, können Sie auf die Anzeige des Python-Interpreters klicken (oder den Befehl Python: Interpreter auswählen aus der Befehlspalette ausführen) und den Python-Interpreter im Container manuell auswählen.

Wir sind nun bereit, zum nächsten Abschnitt überzugehen, in dem wir die Datenspeicherung ersetzen.

Die Datenbank ersetzen

Wir haben ein Dictionary, das die Einkaufslistenartikel speichert, aber wir möchten es durch eine Redis-Datenbank ersetzen. In diesem Tutorial verwenden wir Redis-Hashes, um unsere Daten zu speichern, eine Datenstruktur, die mehrere Schlüssel-Wert-Paare speichern kann.

Im Gegensatz zu einer herkömmlichen Datenbank, bei der Sie einen Artikel abrufen können, ohne seine ID zu kennen, müssen Sie den Redis-Hash-Schlüssel kennen, um einen Wert daraus abzurufen. In diesem Tutorial erstellen wir einen Hash namens item_name_to_id, um Artikel anhand ihres Namens abzurufen und sie ihren IDs zuzuordnen. Zusätzlich erstellen wir weitere Hashes, um Artikel anhand ihrer IDs abzurufen und sie ihren Namen und Mengen zuzuordnen. Jeder Artikel-Hash heißt item_id:{item_id} und hat zwei Felder: item_name und quantity.

Beginnen wir damit, das Dictionary durch ein Redis-Client-Objekt zu ersetzen, das sich mit einem Redis-Server verbindet.

  1. Ersetzen Sie in der Datei main.py die Zeile grocery_list: dict[int, ItemPayload] = {} am Anfang der Datei durch die folgenden Zeilen

    redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)
    

    Pylance wird eine Fehlermeldung anzeigen, da Redis noch nicht importiert wurde.

  2. Setzen Sie den Cursor auf "redis" im Editor und klicken Sie auf die angezeigte Glühbirne (oder auf ⌘. (Windows, Linux Ctrl+.)). Wählen Sie dann 'import redis' hinzufügen.

    Light bulb displayed next to the Redis variable, with the option to add the import statement

    Tipp: Sie können Pylance so einrichten, dass Importe automatisch hinzugefügt werden, indem Sie in den Einstellungen nach der Einstellung Automatische Importvervollständigungen suchen (⌘, (Windows, Linux Ctrl+,)) und diese aktivieren.

    Wir haben nun ein Redis-Client-Objekt, das sich mit einem Redis-Server verbindet, der auf dem lokalen Host läuft (host="0.0.0.0") und auf Port 6379 (port=6379) lauscht. Der Parameter db gibt die zu verwendende Redis-Datenbank an. Redis unterstützt mehrere Datenbanken, und in diesem Code verwenden wir die Datenbank 0, die Standarddatenbank. Wir übergeben auch decode_responses=True, damit die Antworten als Strings (anstatt als Bytes) dekodiert werden.

    Nehmen wir einige weitere Ersetzungen in der ersten Route add_item vor. Anstatt alle Schlüssel aus dem Dictionary zu prüfen, um den Namen des Artikels zu finden, der übergeben wurde, können wir diese Informationen direkt aus einem Redis-Hash abrufen.

    Wir gehen davon aus, dass der Hash item_name_to_id bereits existiert und Artikelnamen seinen IDs zuordnet (keine Sorge, diesen Code werden wir gleich hinzufügen!). Wir können dann die ID des Artikelnamens, den wir in der Anfrage erhalten, abrufen, indem wir die Methode hget von Redis aufrufen, die die Artikel-ID zurückgibt, wenn der angeforderte Name bereits im Hash vorhanden ist, oder None, wenn er nicht vorhanden ist.

  3. Löschen Sie die Zeile mit dem folgenden Inhalt

    items_ids = {item.item_name: item.item_id if item.item_id is not None else 0 for item in grocery_list.values()}
    

    Und ersetzen Sie sie durch

      item_id = redis_client.hget("item_name_to_id", item_name)
    

    Beachten Sie, dass Pylance bei dieser Änderung ein Problem meldet. Dies liegt daran, dass die Methode hget entweder str oder None zurückgibt (wenn der Artikel nicht existiert). Die Zeilen unter dem noch nicht ersetzten Code erwarten jedoch, dass item_id vom Typ int ist. Lassen Sie uns diese Warnung beheben, indem wir das Symbol item_id umbenennen.

  4. Benennen Sie item_id in item_id_str um.

  5. Wenn Sie Inline-Hinweise aktiviert haben, sollte Pylance einen Variablentyp-Hinweis neben item_id_str anzeigen. Sie können optional doppelklicken, um ihn zu akzeptieren

    Variable type hint displayed next to the item_id_str variable

  6. Wenn der Artikel nicht existiert, ist item_id_str None. Jetzt können wir die Zeile mit dem folgenden Inhalt löschen

    if item_name in items_ids.keys():
    

    Und ersetzen Sie sie durch

    if item_id_str is not None:
    

    Jetzt, da wir die Artikel-ID als String haben, müssen wir sie in einen int konvertieren und die Menge für den Artikel aktualisieren. Derzeit ordnet unser Redis-Hash nur Artikelnamen ihren IDs zu. Um auch Artikel-IDs ihren Namen und Mengen zuzuordnen, erstellen wir für jeden Artikel einen separaten Redis-Hash, wobei wir "item_id:{item_id}" als unseren Hash-Namen verwenden, um den Abruf nach ID zu erleichtern. Wir fügen auch die Felder item_name und quantity für jeden dieser Hashes hinzu.

  7. Löschen Sie den Code innerhalb des if-Blocks

    item_id: int = items_ids[item_name]
    grocery_list[item_id].quantity += quantity
    

    Und fügen Sie Folgendes hinzu, um die item_id in einen int zu konvertieren und dann die Menge des Artikels zu erhöhen, indem Sie die Methode hincrby von Redis aufrufen. Diese Methode erhöht den Wert des Feldes "quantity" um den angegebenen Betrag in der Anfrage (quantity)

    item_id = int(item_id_str)
    redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity)
    

    Wir müssen nun nur noch den Code für den Fall ersetzen, dass der Artikel nicht existiert, wenn item_id_str None ist. In diesem Fall generieren wir eine neue item_id, erstellen einen neuen Redis-Hash für den Artikel und fügen dann den angegebenen Artikelnamen und die Menge hinzu.

    Um eine neue item_id zu generieren, verwenden wir die Methode incr von Redis und übergeben einen neuen Hash namens "item_ids". Dieser Hash wird verwendet, um die zuletzt generierte ID zu speichern, sodass wir sie jedes Mal erhöhen können, wenn wir einen neuen Artikel erstellen, um sicherzustellen, dass alle eine eindeutige ID haben.

  8. Löschen Sie die Zeile mit dem folgenden Inhalt

    item_id: int = max(grocery_list.keys()) + 1 if grocery_list else 0
    

    Und fügen Sie Folgendes hinzu

    item_id: int = redis_client.incr("item_ids")
    

    Wenn dieser incr-Aufruf zum ersten Mal mit dem Schlüssel item_ids ausgeführt wird, erstellt Redis den Schlüssel und ordnet ihn dem Wert 1 zu. Jedes Mal, wenn er danach ausgeführt wird, erhöht er den gespeicherten Wert um 1.

    Nun fügen wir den Artikel dem Redis-Hash hinzu, indem wir die Methode hset verwenden und eine Zuordnung für die Felder (item_id, item_name und quantity) und die Werte (die neu erstellte ID des Artikels und sein angegebener Name und seine Menge) bereitstellen.

  9. Löschen Sie die Zeile mit dem folgenden Inhalt

    grocery_list[item_id] = ItemPayload(
            item_id=item_id, item_name=item_name, quantity=quantity
        )
    

    Und ersetzen Sie sie durch Folgendes

    redis_client.hset(
                f"item_id:{item_id}",
                mapping={
                    "item_id": item_id,
                    "item_name": item_name,
                    "quantity": quantity,
                })
    

    Nun müssen wir nur noch die neu erstellte ID dem Artikelnamen zuordnen, indem wir den Hash festlegen, auf den wir anfangs verwiesen haben, item_name_to_id.

  10. Fügen Sie diese Zeile am Ende der Route, innerhalb des else-Blocks, hinzu

    redis_client.hset("item_name_to_id", item_name, item_id)
    
  11. Löschen Sie die Zeile mit dem folgenden Inhalt

    return {"item": grocery_list[item_id]}
    

    Und ersetzen Sie sie durch

    return {"item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity)}
    
  12. Wenn Sie möchten, können Sie versuchen, eine ähnliche Ersetzung für die anderen Routen vorzunehmen. Andernfalls können Sie einfach den gesamten Inhalt der Datei durch die folgenden Zeilen ersetzen

    import redis
    from fastapi import FastAPI, HTTPException
    
    from models import ItemPayload
    
    app = FastAPI()
    
    redis_client = redis.StrictRedis(host="0.0.0.0", port=6379, db=0, decode_responses=True)
    
    # Route to add an item
    @app.post("/items/{item_name}/{quantity}")
    def add_item(item_name: str, quantity: int) -> dict[str, ItemPayload]:
        if quantity <= 0:
            raise HTTPException(status_code=400, detail="Quantity must be greater than 0.")
    
        # Check if item already exists
        item_id_str: str | None = redis_client.hget("item_name_to_id", item_name)
    
        if item_id_str is not None:
            item_id = int(item_id_str)
            redis_client.hincrby(f"item_id:{item_id}", "quantity", quantity)
        else:
            # Generate an ID for the item
            item_id: int = redis_client.incr("item_ids")
            redis_client.hset(
                f"item_id:{item_id}",
                mapping={
                    "item_id": item_id,
                    "item_name": item_name,
                    "quantity": quantity,
                },
            )
            # Create a set so we can search by name too
            redis_client.hset("item_name_to_id", item_name, item_id)
    
        return {
            "item": ItemPayload(item_id=item_id, item_name=item_name, quantity=quantity)
        }
    
    
    # Route to list a specific item by ID but using Redis
    @app.get("/items/{item_id}")
    def list_item(item_id: int) -> dict[str, dict[str, str]]:
        if not redis_client.hexists(f"item_id:{item_id}", "item_id"):
            raise HTTPException(status_code=404, detail="Item not found.")
        else:
            return {"item": redis_client.hgetall(f"item_id:{item_id}")}
    
    
    @app.get("/items")
    def list_items() -> dict[str, list[ItemPayload]]:
        items: list[ItemPayload] = []
        stored_items: dict[str, str] = redis_client.hgetall("item_name_to_id")
    
        for name, id_str in stored_items.items():
            item_id: int = int(id_str)
    
            item_name_str: str | None = redis_client.hget(f"item_id:{item_id}", "item_name")
            if item_name_str is not None:
                item_name: str = item_name_str
            else:
                continue  # skip this item if it has no name
    
            item_quantity_str: str | None = redis_client.hget(
                f"item_id:{item_id}", "quantity"
            )
            if item_quantity_str is not None:
                item_quantity: int = int(item_quantity_str)
            else:
                item_quantity = 0
    
            items.append(
                ItemPayload(item_id=item_id, item_name=item_name, quantity=item_quantity)
            )
    
        return {"items": items}
    
    
    # Route to delete a specific item by ID but using Redis
    @app.delete("/items/{item_id}")
    def delete_item(item_id: int) -> dict[str, str]:
        if not redis_client.hexists(f"item_id:{item_id}", "item_id"):
            raise HTTPException(status_code=404, detail="Item not found.")
        else:
            item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name")
            redis_client.hdel("item_name_to_id", f"{item_name}")
            redis_client.delete(f"item_id:{item_id}")
            return {"result": "Item deleted."}
    
    
    # Route to remove some quantity of a specific item by ID but using Redis
    @app.delete("/items/{item_id}/{quantity}")
    def remove_quantity(item_id: int, quantity: int) -> dict[str, str]:
        if not redis_client.hexists(f"item_id:{item_id}", "item_id"):
            raise HTTPException(status_code=404, detail="Item not found.")
    
        item_quantity: str | None = redis_client.hget(f"item_id:{item_id}", "quantity")
    
        # if quantity to be removed is higher or equal to item's quantity, delete the item
        if item_quantity is None:
            existing_quantity: int = 0
        else:
            existing_quantity: int = int(item_quantity)
        if existing_quantity <= quantity:
            item_name: str | None = redis_client.hget(f"item_id:{item_id}", "item_name")
            redis_client.hdel("item_name_to_id", f"{item_name}")
            redis_client.delete(f"item_id:{item_id}")
            return {"result": "Item deleted."}
        else:
            redis_client.hincrby(f"item_id:{item_id}", "quantity", -quantity)
            return {"result": f"{quantity} items removed."}
    
    
  13. Führen Sie den Debugger erneut aus, um diese Anwendung zu testen, indem Sie mit der Route /docs interagieren. Sie können den Debugger stoppen, sobald Sie fertig sind.

Glückwunsch! Sie haben nun eine funktionierende FastAPI-Anwendung mit Routen zum Hinzufügen, Auflisten und Löschen von Artikeln aus einer Einkaufsliste, und die Daten werden in einer Redis-Datenbank gespeichert.

Optional: Datenbanklöschung einrichten

Da die Daten nun von Redis persistent gemacht werden, möchten Sie möglicherweise ein Skript erstellen, um alle Testdaten zu löschen. Erstellen Sie dazu eine neue Datei namens flushdb.py mit dem folgenden Inhalt

import redis

redis_client = redis.StrictRedis(host='0.0.0.0', port=6379, db=0, decode_responses=True)
redis_client.flushdb()

Wenn Sie die Datenbank zurücksetzen möchten, können Sie die Datei flushdb.py in VS Code öffnen und die Schaltfläche Ausführen in der oberen rechten Ecke des Editors auswählen oder den Befehl Python: Python-Datei im Terminal ausführen aus der Befehlspalette ausführen.

Beachten Sie, dass dies mit Vorsicht geschehen sollte, da alle Schlüssel in der aktuellen Datenbank gelöscht werden, was bei der Ausführung in einer Produktionsumgebung zu Datenverlust führen kann.

Optional: Eine GPT-Aktion erstellen

Mit GitHub Codespaces können Sie Ihre Anwendung zu Testzwecken hosten, wenn Sie GPT Actions verwenden. GPT Actions sind Tools, die es ChatGPT ermöglichen, mit bestehenden APIs zu interagieren, um die Fähigkeiten von ChatGPT zu erweitern und es eine breite Palette von Aktionen ausführen zu lassen. Sie können dem Live-Stream-Mitschnitt unten folgen, um Ihr eigenes Einkaufslisten-Plugin für ChatGPT zu erstellen

Hinweis: Alle persönlichen GitHub.com-Konten haben ein monatliches Freikontingent für die Nutzung von GitHub Codespaces, das in den kostenlosen oder Pro-Plänen enthalten ist. Weitere Informationen finden Sie unter Informationen zur Abrechnung für GitHub Codespaces.

Nächste Schritte

Vielen Dank, dass Sie diesem Tutorial gefolgt sind! Wir hoffen, Sie haben etwas Neues über FastAPI und die Verwendung mit VS Code gelernt.

Das abgeschlossene Code-Projekt aus diesem Tutorial finden Sie auf GitHub: python-sample-vscode-fastapi-tutorial.

Erfahren Sie mehr über FastAPI in der offiziellen Dokumentation.

Um die App auf einer Produktionswebsite auszuprobieren, lesen Sie das Tutorial Python-Apps mit Docker-Containern auf Azure App Service bereitstellen.

Sie können auch diese anderen VS Code Python-Artikel lesen

© . This site is unofficial and not affiliated with Microsoft.