Tutorial: Erstellen Sie eine statische Karte mithilfe von REST-APIs und Python

Fabric Karten werden durch eine public-Definition (map.json) definiert, die das Basemap-, Datenquellen-, Layer- und Renderingverhalten beschreibt.

In diesem Lernprogramm wird ein statisches Datenszenario mithilfe von Dateien veranschaulicht, die in einem Lakehouse gespeichert sind. Informationen zu Echtzeit-Streamingszenarien mit Eventstream und Eventhouse finden Sie unter Create a real-time map using REST APIs and Python.

Die zuverlässigste Methode zum Automatisieren der Kartenerstellung besteht darin, die Kartendefinition inline bereitzustellen, sodass die Karte vollständig konfiguriert und bereit zum Rendern bei der Erstellung ist.

Weitere Informationen zur Struktur der Zuordnungsdefinition finden Sie unter Definition eines Zuordnungselements.

Mit der Fabric REST-API:

  • Erstellen eines Lakehouse mit der Fabric-REST-API
  • Hochladen einer GeoJSON-Datei auf OneLake
  • Hochladen eines benutzerdefinierten SVG-Markierungssymbols auf OneLake
  • Erstellen einer map.json Definition, die auf Lakehouse-Daten verweist
  • Erstellen Sie eine Karte mit der inline angegebenen Definition

Dieses Tutorial folgt einem gängigen Automatisierungsmuster in Fabric: Infrastruktur erstellen → Daten hochladen → Visualisierung definieren → Karte rendern.

Wann sollte dieser Ansatz verwendet werden?

Dieses Muster eignet sich am besten für:

  • Statische georäumliche Datensätze
  • Referenzebenen (z. B. Interessante Punkte, Grenzen)
  • Historische oder im Batch verarbeitete Daten

Szenarien, die eine fortlaufende Aktualisierung von Daten erfordern (z. B. Liveverfolgung oder Telemetrie), finden Sie unter Create a real-time map using REST APIs and Python.

Voraussetzungen

  • Python 3.10 oder höher
  • Azure CLI
  • Fabric-Arbeitsbereichs-ID
  • Berechtigungen zum Aufrufen Fabric REST-APIs, z. B.:
    • Item.ReadWrite.All

Note

Delegierte Bereiche wie Item.ReadWrite.All werden der angemeldeten Identität über ihre Arbeitsbereichsrolle zugewiesen. Stellen Sie sicher, dass der Identität, die Sie mit az login verwenden, im Zielarbeitsbereich von Fabric die Rolle Contributor, Member oder Admin zugewiesen ist, bevor Sie das Skript ausführen.

Authentifizierung

In diesem Tutorial wird DefaultAzureCredential verwendet, das sich mithilfe mehrerer lokaler bzw. Entwicklungsquellen für Anmeldeinformationen authentifizieren kann. Für Erstleser ist die einfachste Methode die Azure CLI-Anmeldung.

  1. Öffnen Sie ein Terminal.
  2. Run:
az login

DefaultAzureCredential kann Ihre angemeldete Identität verwenden, um Zugriffstoken für Folgendes abzurufen:

  • Fabric-REST-APIs (Ressource: https://api.fabric.microsoft.com/.default)
  • OneLake-Zugriff über ADLS Gen2-APIs und SDKs, einschließlich GUID-basierter Adressierung für Arbeitsbereiche und Elemente.

Tipp

Bei https://api.fabric.microsoft.com/.default diesem Wert handelt es sich um einen Tokenanforderungsbereich, nicht um eine URL, die Sie direkt aufrufen. Es weist Microsoft Entra an, dass das Zugriffstoken für die Microsoft Fabric-REST-API ausgestellt werden soll und alle Fabric-Berechtigungen enthalten sollte, die der authentifizierten Identität bereits erteilt wurden (z. B. Item.ReadWrite.All oder Workspace.ReadWrite.All).

Der .default Bereich wird nur während der Tokenerfassung verwendet und nie an Fabric-REST-API-Endpunkte gesendet.

Weitere Informationen zur Funktionsweise des .default Bereichs in der Microsoft Identity Platform finden Sie unter Bereiche und Berechtigungen in der Microsoft Identity Platform.

Bevor Sie dieses Lernprogramm ausführen, empfehlen wir, sich mindestens einmal bei Microsoft Fabric anzumelden:

https://app.fabric.microsoft.com

Durch die Anmeldung wird sichergestellt, dass Ihre Fabric-Identität, Arbeitsbereichsrollenmitgliedschaft und Kapazitätszuweisungen vollständig bereitgestellt werden, bevor Sie ein Microsoft Entra-Zugriffstoken programmgesteuert abrufen.

Dieser Schritt ist besonders hilfreich, wenn:

  • Sie sind neu bei Microsoft Fabric
  • Der Arbeitsbereich wurde kürzlich erstellt.
  • Ihre Rollenzuweisung wurde kürzlich hinzugefügt.

Note

Das Lernprogramm demonstriert das Authentifizieren mithilfe von Microsoft Entra ID über DefaultAzureCredential. Fabric-REST-APIs benötigen keine Browsersitzung, aber die Anmeldung bei der Fabric-Weboberfläche kann Autorisierungsprobleme beim erstmaligen Zugriff verhindern, die durch verzögerte Rollenbereitstellung verursacht werden.

Erstellen der GeoJSON-Datei

Die GeoJSON-Datei in diesem Lernprogramm wird als Datenebene der Karte verwendet. Nachdem Sie die Datei erstellt haben, aktualisieren Sie die local_geojson_path Variable so, dass sie den richtigen Pfad widerspiegelt.

Kopieren Sie den folgenden GeoJSON in eine leere Textdatei, und speichern Sie die Datei unter starbucks-seattle.geojson:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 999 3rd Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334389, 47.605278] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1201 3rd Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.335167, 47.608040] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 221 Pike St" },
      "geometry": { "type": "Point", "coordinates": [-122.340057, 47.609450] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 800 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.330048, 47.604550] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1420 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334091, 47.610041] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1524 7th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.334915, 47.614498] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2011 7th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.338165, 47.616341] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2001 8th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.338806, 47.616848] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 4147 University Way NE" },
      "geometry": { "type": "Point", "coordinates": [-122.313873, 47.658298] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2200 NW Market St" },
      "geometry": { "type": "Point", "coordinates": [-122.384056, 47.668581] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 101 Broadway E" },
      "geometry": { "type": "Point", "coordinates": [-122.320457, 47.620480] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 824 E Pike St" },
      "geometry": { "type": "Point", "coordinates": [-122.320282, 47.614212] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 6501 California Ave SW" },
      "geometry": { "type": "Point", "coordinates": [-122.387016, 47.545376] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 1501 4th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.336212, 47.610325] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 701 5th Ave" },
      "geometry": { "type": "Point", "coordinates": [-122.330704, 47.604298] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2344 Eastlake Ave E" },
      "geometry": { "type": "Point", "coordinates": [-122.325874, 47.640884] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 5221 15th Ave NW" },
      "geometry": { "type": "Point", "coordinates": [-122.376595, 47.668210] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 4408 Fauntleroy Way SW" },
      "geometry": { "type": "Point", "coordinates": [-122.377693, 47.564991] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 7303 35th Ave NE" },
      "geometry": { "type": "Point", "coordinates": [-122.290611, 47.682518] }
    },
    {
      "type": "Feature",
      "properties": { "name": "Starbucks - 2742 Alki Ave SW" },
      "geometry": { "type": "Point", "coordinates": [-122.408028, 47.579311] }
    }
  ]
}

Important

Stellen Sie sicher, dass der in local_geojson_path verwendete Dateipfad mit dem Speicherort übereinstimmt, an dem Sie die Datei auf Ihrem Computer gespeichert haben.

Schritt 1 – Erstellen einer neuen Python-Projektdatei

In diesem Schritt erstellen Sie eine leere Python-Datei, die Sie Abschnitt für Abschnitt erstellen.

Erstellen Sie eine neue Datei mit dem Namen:

create_map_from_geojson.py

Öffnen Sie die Datei in Ihrem Editor.

Schritt 2– Installieren erforderlicher Bibliotheken und Hinzufügen erforderlicher Importanweisungen

In diesem Schritt installieren Sie die Abhängigkeiten, und fügen Sie die Importe hinzu, die Ihr Skript verwendet.

Installieren erforderlicher Bibliotheken

Run:

pip install httpx azure-identity azure-storage-file-datalake

Was für jede Bibliothek vorgesehen ist

  • httpx: sendet HTTP-Anforderungen an die Fabric-REST-APIs.
  • azure-identity: stellt DefaultAzureCredential für Microsoft Entra Authentifizierung bereit.
  • azure-storage-file-datalake: lädt Dateien mithilfe von ADLS Gen2-kompatiblen APIs nach OneLake hoch.

Hinzufügen von Importanweisungen zu Ihrer .py-Datei

Fügen Sie oben in create_map_from_geojson.py Folgendes hinzu:

import base64
import json
import os
import time
import uuid
from pathlib import Path

import httpx
from azure.identity import DefaultAzureCredential
from azure.storage.filedatalake import DataLakeServiceClient

Schritt 3 – Hinzufügen eines Konfigurationsabschnitts

In diesem Schritt definieren Sie die Variablen, die Ihre Anwendung verwendet, einschließlich der Arbeitsbereichs-ID, Dateipfade und Feature-Umschaltflächen.

Die Zentrale Konfiguration in einer einzelnen Config Klasse – anstatt hartcodierte Werte über Funktionen hinweg zu verteilen – bietet Ihnen drei konkrete Vorteile:

  • Portabilität der Umgebung: Arbeitsbereichs-IDs, Dateipfade und Ressourcennamen befinden sich an einem Ort, sodass Sie das Skript für einen anderen Arbeitsbereich oder einen anderen Computer erneut ausführen können, indem Sie einige Zeilen (oder eine Umgebungsvariable) ändern, anstatt den Code zu durchsuchen.
  • Übersichtlichere Funktionssignaturen: Schrittfunktionen akzeptieren ein einzelnes cfg Objekt anstelle langer Parameterlisten, wodurch die Orchestrierung main() leicht lesbar bleibt.
  • Sicherere Handhabung geheimer Schlüssel: Vertrauliche Werte wie die Arbeitsbereichs-ID werden aus Umgebungsvariablen geladen, sodass sie niemals zusammen mit dem Skript zugesichert werden.

Fügen Sie folgendes unter den Importanweisungen hinzu:

# =========================================================
# Configuration (centralized)
# =========================================================

class Config:
    """
    Central configuration: workspace ID, file paths, resource names, and
    toggles for the optional custom SVG marker. A single instance is built
    in main() and passed to each step function.
    """
    def __init__(self):
        # Workspace
        self.workspace_id = os.environ.get("FABRIC_WORKSPACE_ID", "")
        if not self.workspace_id:
            raise RuntimeError("Set FABRIC_WORKSPACE_ID environment variable before running the script.")

        # Local file (source) and OneLake destination paths (inside Lakehouse Files/)
        self.local_geojson_path = Path(r"C:\tutorial\starbucks-seattle.geojson")
        self.geojson_relative_path = "Files/vector/starbucks-seattle.geojson"

        # Optional SVG marker settings
        self.svg_relative_path = "Files/icons/starbucks-marker.svg"
        self.use_custom_svg_marker = True
        self.builtin_icon_name_fallback = "BuildingShop"

        # SVG content (kept < 1 MB, scales cleanly)
        self.starbucks_marker_svg = """\
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
  <path d="M32 2C20.4 2 11 11.4 11 23c0 15.6 18.7 36.6 19.5 37.5a2 2 0 0 0 3 0C34.3 59.6 53 38.6 53 23 53 11.4 43.6 2 32 2z"
        fill="#006241" stroke="#ffffff" stroke-width="2"/>
  <circle cx="32" cy="23" r="13" fill="#ffffff" opacity="0.95"/>
  <path d="M26 20h12v10c0 3-2.5 5-6 5s-6-2-6-5V20z" fill="#006241"/>
</svg>
"""

        # Resource display names / descriptions
        self.lakehouse_display_name = "lh_starbucks_seattle"
        self.lakehouse_description = "Stores Starbucks Seattle GeoJSON + marker icon for a Fabric Maps tutorial"

        self.map_display_name = "My Fabric Map"
        self.map_description = "Created using Fabric Maps REST API"


Festlegen der Arbeitsbereichs-ID mithilfe einer Umgebungsvariable

Anstatt die Arbeitsbereichs-ID direkt im Skript zu codieren, liest dieses Lernprogramm sie aus einer Umgebungsvariable. Dadurch bleiben umgebungsspezifische Werte außerhalb des Quellcodes erhalten, und Sie können das Skript für Arbeitsbereiche oder Computer wiederverwenden, ohne es zu bearbeiten.

Erstellen Sie vor dem Ausführen des Skripts eine Umgebungsvariable mit dem Namen FABRIC_WORKSPACE_ID.

Important

Eine Umgebungsvariable, die von einem Terminal festgelegt wurde, ist nur innerhalb dieser einzelnen Terminalsitzung vorhanden. Sie wird nicht mit anderen Terminalfenstern, mit einem anderen Shelltyp oder mit Prozessen geteilt, die außerhalb dieses Terminals gestartet werden – einschließlich Skripten, die über die Schaltfläche „Ausführen“ in VS Code gestartet werden, wodurch häufig ein eigenes Terminal gestartet wird. Wenn das Skript die Variable nicht finden kann, schlägt es mit dem Fehler Set FABRIC_WORKSPACE_ID environment variable before running the script fehl.

Um dies zu vermeiden, führen Sie entweder das Skript aus der same-Terminalsitzung aus, in der Sie die Variable festlegen, oder legen Sie es dauerhaft fest (siehe die folgenden Abschnitte Windows und macOS/Linux), sodass jede neue Terminalsitzung sie automatisch abholt.

Festlegen der Umgebungsvariable für Windows

Unter Windows können Sie die Variable in jedem Terminal festlegen, das Umgebungsvariablen unterstützt – PowerShell, Windows PowerShell, die in Visual Studio und Visual Studio Code integrierten PowerShell- oder Eingabeaufforderungsfenster, Windows-Terminal und die meisten anderen Shells.

Führen Sie folgendes in PowerShell oder im integrierten VS Code-Terminal aus:

$env:FABRIC_WORKSPACE_ID="<WORKSPACE_ID>"

So bestätigen Sie, dass die Variable festgelegt ist:

echo $env:FABRIC_WORKSPACE_ID

Dadurch wird die Variable nur für die aktuelle Terminalsitzung festgelegt.

Eine persistente Umgebungsvariable festlegen (Windows)

Verwenden Sie eine der folgenden Optionen, um die Variable in zukünftigen Sitzungen verfügbar zu machen:

  • PowerShell (Einzeiler): Ausführen: setx FABRIC_WORKSPACE_ID "<WORKSPACE_ID>". Der setx Befehl nimmt Änderungen an der Benutzerumgebung vor, aktualisiert jedoch nicht das aktuelle Terminal – schließen Sie das Terminal und öffnen Sie es erneut (oder öffnen Sie ein neues), bevor Sie das Skript ausführen.
  • GUI:
    1. Öffnen Sie die Systemeigenschaften.
    2. Wählen Sie erweiterte Systemeinstellungen aus.
    3. Wählen Sie "Umgebungsvariablen" aus.
    4. Wählen Sie unter Benutzervariablen"Neu" aus.
    5. Eintreten:
      • Name: FABRIC_WORKSPACE_ID
      • Wert: Ihre Arbeitsbereichs-ID
    6. Wählen Sie "OK" aus, um sie zu speichern.
    7. Schließen Sie das Terminal, und öffnen Sie es erneut, bevor Sie das Skript erneut ausführen.

Festlegen der Umgebungsvariable unter macOS oder Linux

Unter macOS und Linux können Sie die Variable aus jeder Shell festlegen, die export unterstützt– Bash, Zsh (standard auf modernen macOS), Fish (mit einer etwas anderen Syntax) und die integrierten Terminals in Visual Studio Code und anderen Editoren.

Run:

export FABRIC_WORKSPACE_ID="<WORKSPACE_ID>"

So bestätigen Sie, dass die Variable festgelegt ist:

echo $FABRIC_WORKSPACE_ID

Dadurch wird die Variable nur für die aktuelle Shellsitzung festgelegt.

Eine persistente Umgebungsvariable festlegen (macOS oder Linux)

Um die Variable in zukünftigen Sitzungen verfügbar zu machen, fügen Sie die export Zeile zu Ihrem Shellprofil hinzu:

  • Zsh (Standard unter macOS): ~/.zshrc
  • Bash: ~/.bashrc (Linux) oder ~/.bash_profile (macOS)
  • Fish: Ausführen set -Ux FABRIC_WORKSPACE_ID "<WORKSPACE_ID>" statt Bearbeiten einer Datei

Öffnen Sie nach dem Aktualisieren des Profils entweder ein neues Terminal oder führen Sie source ~/.zshrc aus (oder die entsprechende Datei), damit die Änderung wirksam wird.

Note

Die Werte geojson_relative_path und svg_relative_path definieren den Speicherort innerhalb des Bereichs „Lakehouse Files“. Diese Pfade sind relativ zum Lakehouse-Stamm und werden sowohl zum Hochladen von Dateien als auch zum Verweisen auf sie in der Kartendefinition verwendet.

Schritt 4 – Hinzufügen von Hilfsfunktionen

In diesem Schritt lagern Sie querschnittliche Belange – Authentifizierung, das Erstellen von Headern, Polling für lang andauernde Vorgänge und wiederholbare Uploads auf der Datenebene – in einen kleinen Satz wiederverwendbarer Hilfsfunktionen aus, die von jeder Schrittfunktion aufgerufen werden können.

Diese Aspekte in Hilfsfunktionen zu zentralisieren – anstatt sie direkt an jeder Aufrufstelle einzubetten – bietet Ihnen drei konkrete Vorteile:

  • Eine einzige Quelle der Wahrheit für grenzüberschreitende Bedenken: Authentifizierung, Header und LRO-Abrufe werden von fast jedem API-Aufruf benötigt. Ihre Zentralisierung sorgt dafür, dass sich jede einzelne Step Function auf ihre eigene Ressource konzentrieren kann, anstatt die Tokenbeschaffung und die Logik für Wiederholungsversuche erneut zu implementieren.
  • Resilienz ohne Ballast: Hilfsroutinen fangen vorübergehende Zustände ab – asynchrone Bereitstellung, Propagationsverzögerungen im Backend, Uploadfehler, bei denen ein erneuter Versuch möglich ist – sodass die Schritte kurz bleiben und sich wie eine Checkliste lesen.
  • Einfacher zu vermitteln und anzupassen: Jeder Helfer wird einmal definiert und wiederverwendet. Wenn Fabric ein LRO-Muster oder einen Autorisierungsbereich ändert, passen Sie es an einer einzigen Stelle an.

Die Helfer, die Sie in diesem Schritt hinzufügen, sind:

  • Auth-Hilfsprogramme: Erstellen von Headern für Fabric REST-APIs (und Power BI Cluster-LRO-Endpunkte)
  • FabricClient: einfacher Wrapper für konsistente API-Aufrufe
  • LRO-Handler: zum Abfragen lang andauernder Vorgänge mit Location / x-ms-operation-id / Retry-After, einschließlich Antworten mit 200 und Running, Power BI-Clusterendpunkten und Abschlussnutzlasten, die nur aus einem Status bestehen (aufgelöst durch displayName)
  • Hilfsfunktion für Definitions-Payload: map.json für Inline-Definitionen Base64-kodieren
  • OneLake-Uploadhilfen: GeoJSON- und SVG-Dateien mit Wiederholungsversuchen in Lakehouse Files hochladen

Note

Dieses Lernprogramm umfasst zwei Ebenen:

  • Steuerungsebene (Fabric-REST-APIs): Lakehouse- und Map-Elemente erstellen
  • Datenebene (OneLake DFS): Dateien in das Lakehouse hochladen

Beide sind erforderlich, um die Karte vollständig zu konfigurieren.

Erstellen von Authentifizierungshilfsfunktionen

Jeder Fabric-REST-Aufruf in diesem Lernprogramm enthält im Header Authorization ein Microsoft Entra-Zugriffstoken (Bearer-Token). Anstatt Tokens ad hoc abzurufen, kapselt dieser Schritt DefaultAzureCredential in ein kleines TokenProvider und stellt für jede Endpunktfamilie, die das Skript aufruft, einen audienzspezifischen Header-Generator bereit.

Die Zentralisierung des Tokenabrufs und der Header-Erstellung in Hilfsfunktionen — anstatt Token an jeder Aufrufstelle abzurufen — bietet Ihnen drei konkrete Vorteile:

  • Centralized credential: Ein einzelner DefaultAzureCredential wird in TokenProvider eingeschlossen und für jeden API-Aufruf wiederverwendet, sodass die Identitätsermittlung (Azure CLI, VS Code, verwaltete Identität usw.) einmal erfolgt.
  • Audience-fähige Token: Fabric REST-APIs und Power BI Cluster-LRO-Endpunkte erfordern Token, die für verschiedene Zielgruppen ausgegeben werden. Ein separater Header-Generator pro Zielgruppe hält den richtigen Gültigkeitsbereich direkt neben der Aufrufstelle, sodass sofort ersichtlich ist, welchen Endpunkt jede Funktion anspricht.
  • Neu bei jeder Anforderung: Header-Generatoren erstellen den Authorization Header bei Bedarf, anstatt das Token selbst zwischenspeichern zu müssen. Die zugrunde liegende Anmeldeinformation wird im Hintergrund automatisch erneuert, sodass sich die Aufrufstellen nie Gedanken über den Ablauf machen müssen.

In diesem Lernprogramm werden Fabric REST-APIs mithilfe delegierter Bereiche wie Item.ReadWrite.All (oder Lakehouse.ReadWrite.All für Lakehouse-spezifische Vorgänge) aufgerufen.

Fügen Sie folgendes nach der Config Klasse hinzu:

# =========================================================
# Auth helpers
#
# Authentication utilities built on `DefaultAzureCredential` that acquire and
# construct Authorization headers for calling Fabric REST APIs.
# =========================================================

class TokenProvider:
    """
    Thin wrapper around `DefaultAzureCredential` that acquires Entra access
    tokens. `_fabric_headers()` and `_pbi_headers()` call `get()` per
    request so the Authorization header is always fresh; the underlying
    credential refreshes transparently.
    """
    def __init__(self):
        self._cred = DefaultAzureCredential()

    def get(self, scope: str) -> str:
        return self._cred.get_token(scope).token


_tokens = TokenProvider()


def _fabric_headers() -> dict[str, str]:
    """
    Build headers for Fabric REST API calls.

    This function is called each time we make a Fabric REST call so the token is fresh.
    """
    return {
        "Authorization": f"Bearer {_tokens.get('https://api.fabric.microsoft.com/.default')}",
        "Content-Type": "application/json"
    }


def _pbi_headers() -> dict[str, str]:
    """
    Build headers for polling Power BI cluster LRO endpoints
    (e.g., df-*.analysis.windows.net) that require a Power BI audience token.
    """
    return {
        "Authorization": f"Bearer {_tokens.get('https://analysis.windows.net/powerbi/api/.default')}",
        "Content-Type": "application/json"
    }

Note

Einige länger andauernde Fabric-Vorgänge (Long-Running Operations, LROs) werden auf Power BI-Clusterendpunkten (*.analysis.windows.net) und nicht auf api.fabric.microsoft.com gehostet. Für diese Endpunkte ist ein Power BI Benutzergruppentoken erforderlich, sodass das LRO-Hilfsprogramm automatisch zu _pbi_headers() wechselt, wenn diese Abruf-URL erkannt wird.

Erstellen Sie einen Fabric-Clientwrapper

Die meisten Fabric REST-Aufrufe in diesem Lernprogramm senden dieselben Authorization und Content-Type Header. Anstatt sie an jeder Aufrufstelle zu wiederholen, umschließt dieses Lernprogramm httpx.Client in einem kleinen FabricClient Wrapper, der die Header automatisch anfügt und gleichzeitig das rohe httpx.Response zurückgibt, sodass jeder Aufrufer Statuscodes prüfen kann (z. B. um 201 von 202 zu unterscheiden).

httpx.Client auf diese Weise zu umschließen – anstatt headers=_fabric_headers() bei jedem Aufruf zu übergeben – bringt Ihnen zwei konkrete Vorteile:

  • Kopfzeilen an einer zentralen Stelle: Jede Anrufwebsite nimmt die neueste _fabric_headers() automatisch auf, sodass eine neue Anforderung nicht versehentlich ohne den Authorization Header gesendet werden kann.
  • Statuscodes bleiben sichtbar: request() gibt das rohe httpx.Response statt decodiertem JSON zurück, sodass Aufrufstellen weiterhin anhand des Status (201 vs. 202) verzweigen und Header wie Location oder Retry-After für die LRO-Handhabung prüfen können.

Fügen Sie Folgendes nach den Authentifizierungshilfsfunktionen hinzu:

# =========================================================
# FabricClient (minimal wrapper so call sites stay clean)
# =========================================================

class FabricClient:
    """
    Small wrapper around httpx.Client so we don't repeat headers everywhere.

    Keeps the tutorial behavior:
    - request() returns the raw httpx.Response so the caller can handle 201 vs 202.
    """
    def __init__(self, http_client: httpx.Client):
        self._http = http_client

    def request(self, method: str, url: str, *, json_body=None) -> httpx.Response:
        return self._http.request(method, url, headers=_fabric_headers(), json=json_body)

Erstellen einer LRO-Hilfsfunktion

Mehrere Fabric-REST-APIs, die in diesem Tutorial verwendet werden — wie etwa Create Lakehouse und Create Map — unterstützen lang andauernde Vorgänge (LROs).

Diese APIs können Antworten in verschiedenen Mustern zurückgeben:

  • 201 Created mit dem Ressourcentext inline (synchron)
  • 202 Accepted mit einer Location Kopfzeile, die auf eine Vorgangsstatus-URL zeigt (asynchron)
  • 202 Accepted mit einem x-ms-operation-id Header anstelle von Location (asynchrone, alternative Form)
  • 200 OK mit status: "Running" oder status: "NotStarted" während der Abfrage (noch in Bearbeitung)
  • 200 OK mit status: "Succeeded", aber keine Ressourcen-ID im Textkörper (erfolgreich; auflösen durch Auflisten und Abgleichen von displayName)

Um all diese konsistent zu verarbeiten, erstellen Sie eine einzige Hilfsfunktion, die:

  1. Gibt die Ressourcen-ID sofort zurück, wenn die ursprüngliche Antwort sie bereits enthält.
  2. Andernfalls wird die Operations-URL, die aus Location oder x-ms-operation-id erstellt wird, unter Verwendung von Retry-After abgefragt.
  3. Behandelt 200 OK mit status: "Running" / "NotStarted" weiterhin als noch in Bearbeitung und setzt die Abfrage fort.
  4. Bei Erfolg wird die Ressourcen-ID aus dem Antworttextkörper zurückgegeben, oder es wird auf das Auflisten von Ressourcen und den Abgleich anhand von displayName (mit Wiederholungsversuchen) zurückgegriffen, wenn der Antworttextkörper nur den Status enthält.
  5. Verwendet _pbi_headers(), wenn sich die Abfrage-URL auf einem Power BI-Cluster (*.analysis.windows.net) befindet, andernfalls Fabric-Header.

Diese einzelne Hilfsfunktion ersetzt die Notwendigkeit von Hilfsfunktionen zur „Auflösung nach Namen“ für jede Ressource – jede Funktion create_* in diesem Tutorial ruft _handle_lro mit den jeweils passenden list_url und match_display_name auf.

Fügen Sie folgendes nach der FabricClient Klasse hinzu:

# =========================================================
# LRO handler 
# =========================================================

def _handle_lro(
    client: httpx.Client,
    initial_response: httpx.Response,
    *,
    list_url: str | None = None,
    match_display_name: str | None = None,
    id_field: str = "id",
    max_attempts: int = 10,
    delay: int = 5,
) -> str:
    """
    Handle a Fabric long-running operation (LRO) and return the resource id.

    Supports the response patterns used by Fabric REST APIs:
    - 200/201 with the resource body inline (synchronous).
    - 202 with a `Location` header or `x-ms-operation-id` (asynchronous).
    - 200 with `status: "Running"` / `"NotStarted"` while polling.
    - 200 with `status: "Succeeded"` but no id (resolve by listing and matching `displayName`).

    Polling uses `Retry-After` and switches to a Power BI audience token when
    the operation URL is on `*.analysis.windows.net`.
    """
    # Sync 200/201 with body: return the id immediately.
    if initial_response.status_code in (200, 201):
        try:
            body = initial_response.json() if initial_response.content else {}
        except ValueError:
            body = {}
        if isinstance(body, dict) and body.get(id_field):
            return body[id_field]

    # Location header, with x-ms-operation-id fallback.
    op_url = initial_response.headers.get("Location")
    if not op_url:
        op_id = initial_response.headers.get("x-ms-operation-id")
        if op_id:
            op_url = f"https://api.fabric.microsoft.com/v1/operations/{op_id}"
        else:
            raise RuntimeError(
                f"Missing LRO Location/x-ms-operation-id. "
                f"status={initial_response.status_code} body={initial_response.text[:500]!r}"
            )

    # Audience-aware polling: Power BI cluster endpoints need a different token.
    poll_headers = _pbi_headers() if "analysis.windows.net" in op_url else _fabric_headers()
    retry_after = int(initial_response.headers.get("Retry-After", "5"))

    while True:
        time.sleep(retry_after)
        poll = client.get(op_url, headers=poll_headers)

        if poll.status_code == 202:
            retry_after = int(poll.headers.get("Retry-After", "5"))
            continue

        poll.raise_for_status()
        body = poll.json() if poll.content else {}
        status = body.get("status") if isinstance(body, dict) else None

        if status in ("Running", "NotStarted"):
            retry_after = int(poll.headers.get("Retry-After", "5"))
            continue
        if status == "Failed":
            raise RuntimeError(f"LRO failed. Body: {body}")

        if isinstance(body, dict) and body.get(id_field):
            return body[id_field]

        # Status-only success: list and match by displayName, with retries.
        if status == "Succeeded" and list_url and match_display_name:
            for attempt in range(max_attempts):
                r = client.get(list_url, headers=_fabric_headers())
                r.raise_for_status()
                match = next(
                    (i for i in r.json().get("value", []) if i.get("displayName") == match_display_name),
                    None,
                )
                if match and match.get(id_field):
                    return match[id_field]
                time.sleep(delay)
            raise RuntimeError(
                f"LRO succeeded but resource not visible after retries. "
                f"match_display_name={match_display_name!r}"
            )

        raise RuntimeError(f"LRO completed but no resource id was returned. Body: {body}")

Note

Neu erstellte Ressourcen werden aufgrund von Verzögerungen bei der Back-End-Verteilung möglicherweise nicht sofort angezeigt, wenn Listen-APIs aufgerufen werden. Die Hilfsfunktion wird automatisch erneut ausgeführt, bis die Ressource sichtbar wird.

Helfer für Definitions-Payload

Wenn Sie eine Karte mit einer öffentlichen Definition erstellen, erwartet die REST-API zum Erstellen der Karte, dass jeder Teil in definition.parts eine Base64-codierte Nutzlast mit "payloadType": "InlineBase64" enthält. Das Hilfsprogramm _json_to_b64 kodiert ein Python-dict (Ihr map.json) in dieses Format, damit create_map es direkt in den Request-Body einfügen kann.

Fügen Sie folgendes nach der _handle_lro Funktion hinzu:

# =========================================================
# Definition payload helper
#
# Encodes map.json as base64 for inline Create map payloads.
# =========================================================

def _json_to_b64(obj: dict) -> str:
    """
    Convert a Python dict to base64-encoded JSON text.

    Fabric Map "Create map with definition inline" requires:
    - definition.parts[].payloadType = InlineBase64
    - definition.parts[].payload     = base64(json(map_json))
    """
    return base64.b64encode(json.dumps(obj).encode("utf-8")).decode("utf-8")

OneLake-Uploadassistenten

OneLake unterstützt ADLS/Blob-APIs und ermöglicht GUID-basierte Adressierung für Arbeitsbereiche und Elemente:

https://onelake.dfs.fabric.microsoft.com/<workspaceGUID>/<itemGUID>/<path>/<fileName>

Hinzufügen:

# ===============================================================================================
# ONE LAKE UPLOAD HELPERS
# OneLake supports GUID-based addressing:
#   https://onelake.dfs.fabric.microsoft.com/<workspaceGUID>/<itemGUID>/<path>/<fileName> 
# We use the ADLS Gen2 SDK (DataLakeServiceClient) to upload files into the Lakehouse Files area.
# ===============================================================================================

def _onelake_client() -> DataLakeServiceClient:
    """
    Build a DataLakeServiceClient against the OneLake DFS endpoint,
    authenticated with `DefaultAzureCredential`. Used by `_upload_with_retry`
    to write files into the Lakehouse Files area.
    """
    return DataLakeServiceClient(
        account_url="https://onelake.dfs.fabric.microsoft.com",
        credential=DefaultAzureCredential()
    )


def _upload_with_retry(
    workspace_guid: str,
    item_guid: str,
    dest_relative_path: str,
    content: bytes,
    attempts: int = 6
) -> None:
    """
    Upload bytes into OneLake at `<workspace GUID>/<item GUID>/<relative path>`.
    Retries with linear backoff because a newly created Lakehouse can
    briefly return errors before its `Files/` area is provisioned.
    """
    service = _onelake_client()
    fs = service.get_file_system_client(file_system=workspace_guid)

    dest_path = f"{item_guid}/{dest_relative_path}".replace("\\", "/")

    last_exc = None
    for i in range(attempts):
        try:
            fs.get_file_client(dest_path).upload_data(content, overwrite=True)
            return
        except Exception as exc:
            last_exc = exc
            time.sleep(2 + i)

    raise RuntimeError(f"Upload failed after {attempts} attempts: {last_exc}")


Tipp

Sie können überprüfen, ob die Datei erfolgreich hochgeladen wurde, indem Sie im Fabric-Portal zum Lakehouse Files-Bereich navigieren.

Erstellen primärer Funktionen

Als Nächstes fügen Sie die primären Funktionen hinzu, die den Workflow definieren. Diese werden alle von main() aufgerufen.

  1. Erstellen eines Lakehouse
  2. Hochladen von GeoJSON in das Lakehouse
  3. Hochladen einer benutzerdefinierten SVG-Markierung (optional)
  4. Erstellen der Kartendefinition (map.json)
  5. Erstellen Sie die Map mit ihrer Definition direkt in der Anweisung.

Erstellen eines Lakehouse

create_lakehouse erstellt das Lakehouse, das die GeoJSON-Datei und die optionale SVG-Markierung speichert, die von der Karte verwendet wird.

Diese Funktion bewirkt Folgendes:

  • Sendet eine POST-Anforderung mit displayName und description aus Ihrer Konfiguration an den Lakehouse-REST-Endpunkt.
  • Übergibt die Antwort an _handle_lro, die synchrone Antworten (201), asynchrone (202/LRO) und statusgeschützte Antworten einheitlich verarbeitet.
  • Gibt die Lakehouse-ID für die Verwendung in späteren Schritten zurück.

Fügen Sie folgendes nach der _upload_with_retry Funktion hinzu:

# =========================================================
# Step 1: Create a Lakehouse
# =========================================================

def create_lakehouse(client: httpx.Client, fabric: FabricClient, cfg: Config) -> str:
    """
    Create a Lakehouse and return its item ID.
    """
    lakehouse_url = f"https://api.fabric.microsoft.com/v1/workspaces/{cfg.workspace_id}/lakehouses"
    lakehouse_payload = {
        "displayName": cfg.lakehouse_display_name,
        "description": cfg.lakehouse_description
    }

    lh_resp = fabric.request("POST", lakehouse_url, json_body=lakehouse_payload)

    lakehouse_id = _handle_lro(
        client,
        lh_resp,
        list_url=lakehouse_url,
        match_display_name=cfg.lakehouse_display_name,
    )

    print("Lakehouse created. Lakehouse ID:", lakehouse_id)
    return lakehouse_id

Hochladen von GeoJSON in das Lakehouse

upload_geojson lädt die lokale GeoJSON-Datei in das Lakehouse-Gebiet Files hoch, wo sie zur räumlichen Datenquelle wird, die die Karte zur Renderzeit liest.

Dies ist der erste Schritt, der von der Fabric-Steuerebene (REST) in die OneLake-Datenebene (ADLS Gen2) übergeht. Die Funktion liest die lokale Datei in den Arbeitsspeicher und delegiert an _upload_with_retry, das den chunkweisen DFS-Upload ausführt und bei vorübergehenden Fehlern Wiederholungsversuche durchführt.

Fügen Sie folgendes nach der create_lakehouse Funktion hinzu:

# =========================================================
# Step 2: Upload GeoJSON to the Lakehouse
# =========================================================

def upload_geojson(cfg: Config, lakehouse_id: str) -> None:
    """
    Upload the local GeoJSON file to the Lakehouse Files area at
    `cfg.geojson_relative_path` using the OneLake DFS endpoint.
    """
    _upload_with_retry(
        workspace_guid=cfg.workspace_id,
        item_guid=lakehouse_id,
        dest_relative_path=cfg.geojson_relative_path,
        content=cfg.local_geojson_path.read_bytes()
    )
    print("Uploaded GeoJSON to:", cfg.geojson_relative_path)

Hochladen einer benutzerdefinierten SVG-Markierung

upload_svg_marker lädt ein benutzerdefiniertes SVG-Icon in dasselbe Lakehouse hoch, sodass die Karte jedes Feature mit diesem Marker anstelle eines integrierten Markers rendern kann. Der Schritt ist optional und wird durch cfg.use_custom_svg_marker gesteuert — wenn das Flag False ist, kehrt die Funktion sofort zurück, und die Karte greift auf einen integrierten Marker zurück.

Wie bei upload_geojson delegiert diese Funktion den eigentlichen Upload an _upload_with_retry.

Fügen Sie folgendes nach der upload_geojson Funktion hinzu:

# =========================================================
# Step 3: Upload a custom SVG marker (optional)
# =========================================================

def upload_svg_marker(cfg: Config, lakehouse_id: str) -> None:
    """
    Upload a custom SVG marker to the Lakehouse at
    `cfg.svg_relative_path` when `cfg.use_custom_svg_marker` is True;
    otherwise return without uploading.
    """
    if not cfg.use_custom_svg_marker:
        return

    _upload_with_retry(
        workspace_guid=cfg.workspace_id,
        item_guid=lakehouse_id,
        dest_relative_path=cfg.svg_relative_path,
        content=cfg.starbucks_marker_svg.encode("utf-8")
    )
    print("Uploaded custom SVG marker to:", cfg.svg_relative_path)

Tipp

SVG-Markierungen werden übersichtlich über Zoomstufen und Bildschirm-DPIs skaliert, wodurch sie gut für Kartensymbole geeignet sind.

map.json erstellen

build_map_json erstellt und gibt die map.json Payload zurück, die den Inhalt der Fabric Map definiert. Die Nutzlast folgt dem Schema der Kartenelementdefinition und besteht aus vier Abschnitten: dataSources (wo Daten stammen), iconSources (optionale benutzerdefinierte Markierungen), layerSources (was gelesen wird und wie oft) und layerSettings (wie das Ergebnis auf der Karte gerendert wird).

In diesem Tutorial verweist dataSources auf das zuvor erstellte Lakehouse (itemType: "Lakehouse"), und der einzelne Eintrag in layerSources ist ein GeoJSON-Datei-Layer (type: "geojson"), der die Datei liest, die Sie über relativePath hochgeladen haben. refreshIntervalMs ist auf 0 festgelegt, weil die Quelldatei statisch ist – die Zuordnung rendert die Datei nur einmal und prüft nicht auf Änderungen.

Der übereinstimmende layerSettings-Eintrag stellt jedes Feature als marker dar und zeigt die GeoJSON-Eigenschaft name in Tooltips an. Wenn cfg.use_custom_svg_marker auf True gesetzt ist, wird ein iconSources-Eintrag hinzugefügt, der auf die hochgeladene SVG-Datei verweist, und die iconOptions.image des Layers verwendet den zusammengesetzten Schlüssel <layerSettingId>:<iconId>, um die Markierung mit diesem Symbol zu verknüpfen. Wenn es sich um False handelt, greift die Ebene auf eine integrierte Markierung (cfg.builtin_icon_name_fallback) zurück, die mit einer Starbucks-grünen Füllung dargestellt wird.

Weitere Informationen zur REST-API der Kartendefinition finden Sie unter Kartenelementdefinition. Ein Beispiel für ein map.json finden Sie unter MapDetails-Beispiel.

Fügen Sie folgendes nach der upload_svg_marker Funktion hinzu:

# =========================================================
# Step 4: Build map.json
# =========================================================

def build_map_json(cfg: Config, lakehouse_id: str) -> dict:
    """
    Build and return the map.json payload for the Fabric Map.

    Wires `dataSources` to the Lakehouse created earlier, defines a
    single GeoJSON layer in `layerSources` that reads the uploaded file
    via `cfg.geojson_relative_path` with `refreshIntervalMs: 0` (the
    source is static), and configures `layerSettings` to render each
    feature as a marker. When `cfg.use_custom_svg_marker` is True, adds
    an `iconSources` entry for the uploaded SVG and binds the layer to
    it via a `<layerSettingId>:<iconId>` composite key; otherwise falls
    back to a built-in marker.
    """
    layer_source_id = str(uuid.uuid4())
    layer_setting_id = str(uuid.uuid4())
    icon_source_id = str(uuid.uuid4())

    custom_svg_marker = f"{layer_setting_id}:{icon_source_id}"
    icon_source_name = "Starbucks Marker"

    map_json = {
        "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/map/definition/2.0.0/schema.json",
        "basemap": {},

        "dataSources": [
            {"itemType": "Lakehouse", "workspaceId": cfg.workspace_id, "itemId": lakehouse_id}
        ],

        "iconSources": (
            [
                {
                    "id": icon_source_id,
                    "name": icon_source_name,
                    "type": "svg",
                    "itemId": lakehouse_id,
                    "relativePath": cfg.svg_relative_path
                }
            ] if cfg.use_custom_svg_marker else []
        ),

        "layerSources": [
            {
                "id": layer_source_id,
                "name": "starbucks_seattle_geojson",
                "type": "geojson",
                "itemId": lakehouse_id,
                "relativePath": cfg.geojson_relative_path,
                "refreshIntervalMs": 0
            }
        ],

        "layerSettings": [
            {
                "id": layer_setting_id,
                "name": "Starbucks (Seattle)",
                "sourceId": layer_source_id,
                "options": {
                    "type": "vector",
                    "visible": True,
                    "tooltipKeys": ["name"],
                    "pointLayerType": "marker",

                    "markerOptions": (
                        {
                            "iconOptions": {
                                "image": custom_svg_marker,
                                "anchor": "bottom",
                                "opacity": 1.0,
                                "rotation": 0,
                                "allowOverlap": False,
                                "rotationAlignment": "viewport",
                                "pitchAlignment": "viewport"
                            },
                            "icon": icon_source_id
                        }
                        if cfg.use_custom_svg_marker
                        else
                        {
                            "size": 22,
                            "fillColor": "#006241",
                            "strokeColor": "#FFFFFF",
                            "strokeWidth": 2,
                            "icon": cfg.builtin_icon_name_fallback,
                            "iconOptions": {
                                "image": f"{layer_setting_id}:{cfg.builtin_icon_name_fallback}",
                                "anchor": "bottom",
                                "opacity": 1.0,
                                "rotation": 0,
                                "allowOverlap": False,
                                "rotationAlignment": "viewport",
                                "pitchAlignment": "viewport"
                            }
                        }
                    )
                }
            }
        ]
    }

    return map_json


Tipp

Tipps zur Kartendefinition:

  • Die image Eigenschaft verwendet einen zusammengesetzten Schlüssel im Format <layerSettingId>:<iconId> , um auf das Symbol für die Ebene zu verweisen. Dies ordnet die Konfiguration des Markerrenderings der zuvor in der Kartendefinition definierten Symbolquelle zu.
  • Das Festlegen von refreshIntervalMs auf 0 deaktiviert die automatische Aktualisierung. Dies ist für statische GeoJSON-Dateien geeignet, die in einem Lakehouse gespeichert sind.

Eine Karte mit Inline-Definition erstellen

create_map erstellt die Karte durch POSTing der von Ihnen zusammengestellten Inlinedefinition und gibt die Element-ID der neuen Karte zurück. Für dieses Tutorial enthält die Anfrage einen einzelnen Base64-kodierten Teil — map.json —, der in payloadType: "InlineBase64" eingebettet und über _json_to_b64 kodiert ist. Die map.json-Payload verweist bereits auf die Lakehouse-Datenquelle und, sofern vorhanden, auf das SVG-Symbol von relativePath, sodass die Ebene durch den Aufruf „Create Map“ vollständig eingebunden ist, ohne einen nachgelagerten updateDefinition-Roundtrip. Wenn Sie von den Standardeinstellungen abweichende Elementmetadaten festlegen oder eine Git-freundliche logicalId fixieren möchten, fügen Sie demselben parts-Array einen .platform-Teil hinzu; Fabric wendet Standardmetadaten an, wenn .platform nicht angegeben wird, und genau das geschieht in diesem Tutorial.

Die REST-API zum Erstellen von Karten kann mit 201 Created antworten (synchron, ID inline), mit 202 Accepted (asynchrones LRO über Location oder x-ms-operation-id) oder mit 200 OK mit einer Payload nur mit Status zum Abschluss, wobei die Karte in „List Maps“ aufgrund einer backendseitigen Weitergabeverzögerung noch nicht sichtbar ist. _handle_lro deckt all diese Fälle ab – einschließlich Auflistung und Abgleich nach displayName –, sodass diese Funktion die vollständige Antwortverarbeitung in einem einzigen Aufruf delegiert.

Weitere Informationen finden Sie unter Definition des Kartenelements.

Fügen Sie folgendes nach der build_map_json Funktion hinzu:

# =========================================================
# Step 5: Create a map with inline definition
# =========================================================

def create_map(client: httpx.Client, fabric: FabricClient, cfg: Config, map_json: dict) -> str:
    """
    Create the Fabric map with its definition inline and return its item ID.

    Sends a single Create map request whose `parts` array carries one
    base64-encoded payload, `map.json`. The map definition already
    references the Lakehouse data source (and, when present, the SVG
    icon) by `relativePath`, so the layer is wired by the Create Map
    call without a follow-up update. Delegates response handling to
    `_handle_lro`, which covers synchronous, asynchronous, and
    status-only completions.
    """
    create_map_url = f"https://api.fabric.microsoft.com/v1/workspaces/{cfg.workspace_id}/maps"

    create_map_payload = {
        "displayName": cfg.map_display_name,
        "description": cfg.map_description,
        "definition": {
            "parts": [
                {
                    "path": "map.json",
                    "payload": _json_to_b64(map_json),
                    "payloadType": "InlineBase64"
                }
            ]
        }
    }

    map_resp = fabric.request("POST", create_map_url, json_body=create_map_payload)

    return _handle_lro(
        client, map_resp,
        list_url=create_map_url,
        match_display_name=cfg.map_display_name,
    )

Koordinieren des Workflows

main ist der zentrale Einstiegspunkt, der das Tutorial vollständig ausführt. Es instanziiert Config, öffnet ein httpx.Client, das von allen Hilfsfunktionen wiederverwendet wird, kapselt es in ein FabricClient und ruft dann jede Schrittfunktion in der Abhängigkeitsreihenfolge auf: create_lakehouseupload_geojson (schreibt das GeoJSON nach OneLake im neuen Lakehouse) → upload_svg_marker (optional; wird nur ausgeführt, wenn cfg.use_custom_svg_marker gesetzt ist) → build_map_jsoncreate_map.

Die Reihenfolge ist wichtig, da jeder Schritt etwas verwendet, das in einem früheren Schritt erstellt wurde — upload_geojson und upload_svg_marker benötigen die Lakehouse-Element-ID, und build_map_json verweist über relativePath auf beide Uploads, sodass Create Map sie beim Rendern auflösen kann. Das letzte print Block zeigt die Lakehouse-ID, die Karten-ID und die relativen Pfade der hochgeladenen Objekte an, damit Sie sie im Fabric-Portal finden können.

Fügen Sie folgendes nach der create_map Funktion hinzu:

# =========================================================
# main(): orchestrates the full workflow
# =========================================================

def main():
    """
    Orchestrate the tutorial workflow.

    1) Create a Lakehouse
    2) Upload GeoJSON to the Lakehouse
    3) Upload a custom SVG marker (optional)
    4) Build the map definition (map.json)
    5) Create the map with its definition inline
    """
    cfg = Config()

    print("Initializing clients...")
    with httpx.Client(timeout=60) as client:
        fabric = FabricClient(client)

        # Step 1
        lakehouse_id = create_lakehouse(client, fabric, cfg)

        # Step 2
        upload_geojson(cfg, lakehouse_id)

        # Step 3 (optional)
        upload_svg_marker(cfg, lakehouse_id)

        # Step 4
        map_json = build_map_json(cfg, lakehouse_id)

        # Step 5
        map_id = create_map(client, fabric, cfg, map_json)

        print("\nDONE")
        print("Lakehouse ID:", lakehouse_id)
        print("Map ID:", map_id)
        print("GeoJSON layer path:", cfg.geojson_relative_path)
        if cfg.use_custom_svg_marker:
            print("Custom SVG marker path:", cfg.svg_relative_path)


if __name__ == "__main__":
    main()

Zu diesem Zeitpunkt wurden alle Konfigurationen und Code definiert.

Im nächsten Schritt führen Sie das Skript aus, um das Lakehouse zu erstellen, Daten hochzuladen und die Karte zu generieren.

Ausführen der Anwendung

Note

Lakehouse- und Kartenanzeigenamen müssen innerhalb eines Arbeitsbereichs eindeutig sein. Löschen Sie vor der erneuten Ausführung des Skripts entweder die elemente, die auf der vorherigen Ausführung im arbeitsbereich Fabric erstellt wurden, oder ändern Sie lakehouse_display_name / map_display_name in Config. Andernfalls schlagen die Erstellungsaufrufe mit 409 ItemDisplayNameAlreadyInUse fehl.

Führen Sie das Skript aus:

python create_map_from_geojson.py

Wenn das Skript erfolgreich ausgeführt wird, wird die Ausgabe ähnlich wie die folgenden angezeigt:

DONE
Lakehouse ID: <Lakehouse ID>
Map ID: <Map ID>
GeoJSON layer path: Files/vector/starbucks-seattle.geojson
Custom SVG marker path: Files/icons/starbucks-marker.svg

In Microsoft Fabric sollte Ihre Karte wie folgt aussehen:

Ein Screenshot von Microsoft Fabric Maps, der Seattle mit mehreren grünen Starbucks-Markersymbolen zeigt, die in der Innenstadt gruppiert sind. Die Karte zeigt Straßen und Wasserflächen mit einem hellgrauen Hintergrund. Das Panel

Tipp

Wenn die Karte nicht sofort angezeigt wird, aktualisieren Sie den Arbeitsbereich, oder warten Sie einige Sekunden, bis die Back-End-Verteilung abgeschlossen ist.

Zusammenfassung

In diesem Lernprogramm haben Sie eine automatisierte Geospatiallösung mit Microsoft Fabric Karten- und Lakehouse-Daten erstellt.

Sie haben Fabric REST-APIs und Python verwendet, um alle erforderlichen Ressourcen bereitzustellen und zu konfigurieren, und dann in OneLake gespeicherte räumliche Daten visualisiert.

Sie haben Folgendes erreicht:

  • Räumliche Daten in ein Lakehouse hochgeladen
  • Konfiguriertes Dataset für geospatiale Visualisierung
  • Erstellen einer Fabric-Zuordnung mit einer Inline-Definition
  • Karte mit Lakehouse-Daten verbunden
  • Konfigurierte Kartenebenen zum Rendern räumlicher Features

Diese Architektur veranschaulicht ein gängiges Muster für Batch- und historische räumliche Analysen in Fabric:

  • Daten werden in OneLake (Lakehouse) gespeichert.
  • Kartenabfragen und Rendern räumlicher Datasets
  • Ebenen bieten visuelle Einblicke in geografische Daten

Durch die Automatisierung der Ressourcenerstellung mithilfe von Python- und REST-APIs haben Sie jetzt einen wiederholbaren Ansatz zum Erstellen von Geospatialanwendungen basierend auf statischen oder historischen Datasets.

Nächste Schritte

Nachdem Sie nun verstehen, wie Sie räumliche Daten aus einem Lakehouse visualisieren, können Sie diese Lösung erweitern:

  • Kombinieren mehrerer Datasets für eine umfangreichere Geospatialanalyse
  • Anwenden von Formatierungen und Filtern zum Hervorheben von Trends und Mustern
  • Hinzufügen von Referenzebenen wie Begrenzungen oder Routen
  • Integrieren von Datenpipelines zum automatischen Aktualisieren von Datasets
  • Erkunden von Echtzeitstream-Streamingszenarien mit Eventstream und Eventhouse

Weitere Informationen zum Arbeiten mit räumlichen Daten und Karten in Fabric finden Sie unter:

Ein Tutorial, das zeigt, wie Sie mithilfe von REST-APIs eine Echtzeitkarte erstellen, finden Sie unter: