> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-de/erweitert/python-sdk.md).

# Python-SDK-Leitfaden

{% hint style="success" %}
**Neu beim SDK?** Beginnen Sie mit dem [5-minütigen Schnellstart](/guides/guides_v2-de/erste-schritte/python-quickstart.md) zuerst.
{% endhint %}

Für ein Schnellstart-Tutorial mit echten Beispielen siehe [Clore.ai Python SDK — Automatisieren Sie Ihre GPU-Workflows in 5 Minuten](https://blog.clore.ai/cloreai-python-sdk-automate-your-gpu-workflows-in-5-minutes/)

## Installation

```bash
pip install clore-ai
```

Das SDK stellt zwei Clients bereit:

* **`CloreAI`** — synchron (einfacher, gut für Skripte)
* **`AsyncCloreAI`** — asynchron (schneller für gleichzeitige Vorgänge)

Beide teilen sich die gleichen Methoden und geben dieselben Pydantic-Modelle zurück.

***

## Sync vs Async — Wann welches verwenden

| Anwendungsfall                       | Client         | Warum                                 |
| ------------------------------------ | -------------- | ------------------------------------- |
| Einfache Skripte, einmalige Aufgaben | `CloreAI`      | Einfacherer Code, kein `async/await`  |
| Überwachungs-Schleifen               | `CloreAI`      | Sequenzielle Checks funktionieren gut |
| Massive Marketplace-Abfragen         | `AsyncCloreAI` | Gleichzeitige Anfragen = schneller    |
| Batch-Erstellung von Orders          | `AsyncCloreAI` | Erstellen mehrerer Orders parallel    |
| Webanwendungen                       | `AsyncCloreAI` | Nicht-blockierende I/O                |

### Sync-Beispiel

```python
from clore_ai import CloreAI

client = CloreAI()  # Verwendet die Umgebungsvariable CLORE_API_KEY

servers = client.marketplace(gpu="RTX 4090")
print(f"Gefundene Server: {len(servers)}")

client.close()  # Oder verwenden Sie einen Context-Manager
```

### Async-Beispiel

```python
import asyncio
from clore_ai import AsyncCloreAI

async def main():
    async with AsyncCloreAI() as client:
        servers = await client.marketplace(gpu="RTX 4090")
        print(f"Gefundene Server: {len(servers)}")

asyncio.run(main())
```

### Context-Manager (empfohlen)

Beide Clients unterstützen Context-Manager für automatische Aufräumarbeiten:

```python
# Sync
with CloreAI() as client:
    wallets = client.wallets()

# Async
async with AsyncCloreAI() as client:
    wallets = await client.wallets()
```

***

## Client-Konfiguration

```python
client = CloreAI(
    api_key="dein_key",      # Oder setze die Umgebungsvariable CLORE_API_KEY
    base_url="https://api.clore.ai/v1",  # Benutzerdefinierter API-Endpunkt
    timeout=30.0,            # Anfrage-Timeout in Sekunden
    max_retries=3            # Wiederholungen bei Rate-Limit / Netzwerkfehlern
)
```

Das SDK enthält einen eingebauten Rate Limiter:

* **Allgemeine Anfragen:** 1 Anfrage/Sekunde
* **`create_order`:** 5 Sekunden Cooldown zwischen Aufrufen
* **Rate-Limit-Fehler (Code 5):** Automatisches exponentielles Backoff

***

## Marketplace-Filterung

Die `marketplace()` Methode holt alle verfügbaren Server und filtert clientseitig:

```python
from clore_ai import CloreAI

client = CloreAI()

# Alle verfügbaren Server
all_servers = client.marketplace()

# Nach GPU-Modell filtern (case-insensitive Teilstring-Abgleich)
rtx_4090s = client.marketplace(gpu="RTX 4090")

# Nach mehreren Kriterien filtern
budget_gpus = client.marketplace(
    gpu="RTX 4090",
    max_price_usd=1.0,       # Max $1.00/Stunde
    min_gpu_count=2,          # Mindestens 2 GPUs
    min_ram_gb=64.0,          # Mindestens 64GB Systemspeicher
    available_only=True       # Nur verfügbare Server (Standard)
)
```

### Erweiterte Filterung (clientseitig)

Für Filter, die nicht in die Methode integriert sind, filtern Sie die zurückgegebenen `Server` Objekte selbst:

```python
servers = client.marketplace(gpu="RTX 4090")

# Server in der EU mit hoher Zuverlässigkeit
eu_servers = [
    s for s in servers
    if s.location and s.location.upper() in ("DE", "FR", "NL", "FI")
    and s.reliability and s.reliability >= 0.95
]

# Nach Preis sortieren
cheapest = sorted(servers, key=lambda s: s.price_usd or float("inf"))
print(f"Günstigster: Server {cheapest[0].id} — ${cheapest[0].price_usd:.4f}/h")
```

### Server-Modell-Felder

Jedes `MarketplaceServer` Objekt hat diese Attribute und Hilfseigenschaften:

| Feld             | Typ                   | Beschreibung                                                        |
| ---------------- | --------------------- | ------------------------------------------------------------------- |
| `id`             | `int`                 | Server-ID (verwenden Sie dies in `create_order`)                    |
| `gpu_model`      | `str \| None`         | GPU-Beschreibung aus den Spezifikationen (Eigenschaft)              |
| `gpu_count`      | `int`                 | Anzahl der GPUs aus `gpu_array` (Eigenschaft)                       |
| `ram_gb`         | `float \| None`       | Systems-RAM in GB (Eigenschaft, aus `specs.ram`)                    |
| `price_usd`      | `float \| None`       | On-Demand-Preis in USD (Eigenschaft, aus `price.usd.on_demand_usd`) |
| `spot_price_usd` | `float \| None`       | Spot-Preis in USD (Eigenschaft)                                     |
| `available`      | `bool`                | Ob der Server nicht vermietet ist (Eigenschaft)                     |
| `location`       | `str \| None`         | Ländercode aus den Netzwerk-Spezifikationen (Eigenschaft)           |
| `specs`          | `ServerSpecs \| None` | Hardware-Spezifikationen (CPU, RAM, Festplatte, GPU, Netzwerk)      |
| `price`          | `ServerPrice \| None` | Vollständige Preisstruktur                                          |
| `rented`         | `bool \| None`        | Ob der Server derzeit vermietet ist                                 |

***

## Auftragsverwaltung

### Orders erstellen

```python
order = client.create_order(
    server_id=142,
    image="cloreai/ubuntu22.04-cuda12",
    type="on-demand",               # "on-demand" oder "spot"
    currency="bitcoin",             # Zahlungsmittel
    ssh_password="MySecurePass",    # SSH-Zugang
    ports={"22": "tcp", "8888": "http"},  # Port-Mapping
    env={"HF_TOKEN": "hf_xxx"},    # Umgebungsvariablen
    command="bash /start.sh",       # Benutzerdefinierter Startbefehl
    jupyter_token="my_token"        # Jupyter-Notebook-Token
)

print(f"Order ID: {order.id}")
print(f"IP: {order.pub_cluster}")
print(f"Ports: {order.tcp_ports}")
```

### Vollständige `create_order` Parameter

| Parameter            | Typ     | Erforderlich | Beschreibung                         |
| -------------------- | ------- | ------------ | ------------------------------------ |
| `server_id`          | `int`   | ✅            | Server, der gemietet werden soll     |
| `image`              | `str`   | ✅            | Docker-Image                         |
| `type`               | `str`   | ✅            | `"on-demand"` oder `"spot"`          |
| `currency`           | `str`   | ✅            | Zahlungswährung (z. B., `"bitcoin"`) |
| `ssh_password`       | `str`   | —            | SSH-Passwort                         |
| `ssh_key`            | `str`   | —            | SSH-Public-Key                       |
| `ports`              | `dict`  | —            | Port-Mappings (`{"22": "tcp"}`)      |
| `env`                | `dict`  | —            | Umgebungsvariablen                   |
| `jupyter_token`      | `str`   | —            | Jupyter-Notebook-Token               |
| `command`            | `str`   | —            | Startbefehl                          |
| `spot_price`         | `float` | —            | Spot-Gebotspreis                     |
| `required_price`     | `float` | —            | Erforderlicher Preis                 |
| `autossh_entrypoint` | `str`   | —            | Auto-SSH-Einstiegspunkt              |

### Auflistung von Orders

```python
# Nur aktive Orders
active = client.my_orders()
for o in active:
    print(f"Order {o.id}: type={o.type}, IP={o.pub_cluster}, status={o.status}")

# Inklusive abgeschlossener Orders
all_orders = client.my_orders(include_completed=True)
```

### Order-Modell-Felder

| Feld          | Typ             | Beschreibung                           |
| ------------- | --------------- | -------------------------------------- |
| `id`          | `int`           | Order-ID                               |
| `server_id`   | `int \| None`   | Gemietete Server-ID                    |
| `type`        | `str`           | `"on-demand"` oder `"spot"`            |
| `status`      | `str \| None`   | Order-Status                           |
| `image`       | `str \| None`   | Docker-Image                           |
| `currency`    | `str \| None`   | Zahlungswährung                        |
| `price`       | `float \| None` | Preis                                  |
| `pub_cluster` | `str \| None`   | Öffentliche IP / Hostname              |
| `tcp_ports`   | `dict \| None`  | Port-Mappings (z. B., `{"22": 50022}`) |
| `created_at`  | `str \| None`   | Erstellungszeitstempel                 |

### Monitoring von Orders

```python
import time

def wait_for_ready(client, order_id, timeout=120):
    """Warten, bis eine Order eine öffentliche IP erhält."""
    for _ in range(timeout // 10):
        orders = client.my_orders()
        order = next((o for o in orders if o.id == order_id), None)
        if order and order.pub_cluster:
            return order
        time.sleep(10)
    raise TimeoutError(f"Order {order_id} nach {timeout}s nicht bereit")

# Verwendung
order = client.create_order(server_id=142, image="cloreai/ubuntu22.04-cuda12", type="on-demand", currency="bitcoin")
ready = wait_for_ready(client, order.id)
print(f"SSH: ssh root@{ready.pub_cluster} -p {ready.tcp_ports.get('22', 22)}")
```

### Stornierung von Orders

```python
# Stornieren mit optionalem Grund
client.cancel_order(order_id=38, issue="Job complete")

# Alle aktiven Orders stornieren
orders = client.my_orders()
for order in orders:
    client.cancel_order(order.id, issue="Cleanup")
    print(f"Order {order.id} storniert")
```

***

## Server-Verwaltung (für Hoster)

Wenn Sie GPUs bei Clore hosten, ermöglicht das SDK Ihnen, Ihre Server zu verwalten:

### Ihre Server auflisten

```python
my_servers = client.my_servers()
for s in my_servers:
    print(f"Server {s.id}: {s.gpu_model} — {s.status}")
```

### Server-Konfiguration abrufen

```python
config = client.server_config("MyGPU-Rig")
print(f"Name: {config.name}")
print(f"Sichtbarkeit: {config.visibility}")
print(f"Online: {config.online}")
print(f"Minimale Mietzeit: {config.mrl}h")
print(f"On-Demand-Preis: {config.on_demand_price}")
print(f"Spot-Preis: {config.spot_price}")
```

### Server-Einstellungen aktualisieren

```python
client.set_server_settings(
    name="MyGPU-Rig",
    availability=True,       # Server verfügbar machen
    mrl=24,                  # Mindestmietdauer 24h
    on_demand=0.0001,        # On-Demand-Preis in BTC
    spot=0.00000113          # Spot-Preis in BTC
)
print("Einstellungen aktualisiert")
```

***

## Spot-Markt

Spot-Orders sind 30–50% günstiger, können jedoch unterbrochen werden, wenn jemand Sie überbietet.

### Spot-Angebote anzeigen

```python
offers = client.spot_marketplace(server_id=6)
for offer in offers:
    print(f"Order {offer.get('order_id')}: price={offer.get('price')}")
```

### Eine Spot-Order erstellen

```python
order = client.create_order(
    server_id=142,
    image="cloreai/ubuntu22.04-cuda12",
    type="spot",
    currency="bitcoin",
    spot_price=0.0001,       # Ihr Gebotspreis
    ssh_password="MyPass"
)
print(f"Spot-Order {order.id} erstellt")
```

### Spot-Preis anpassen

```python
# Erhöhen Sie Ihr Gebot, um ein Überbieten zu vermeiden
client.set_spot_price(order_id=39, price=0.000003)
```

### Spot-Gebotsstrategie

```python
from clore_ai import CloreAI

client = CloreAI()

def smart_spot_bid(server_id, premium_pct=5):
    """Bieten Sie leicht über dem aktuellen Mindest-Spot-Preis."""
    offers = client.spot_marketplace(server_id=server_id)
    if not offers:
        print("Keine Spot-Angebote — verwenden Sie den On-Demand-Preis als Basis")
        return None

    min_price = min(o["price"] for o in offers)
    bid = min_price * (1 + premium_pct / 100)
    print(f"Markt-Mindestpreis: {min_price}, Gebot: {bid:.8f} (+{premium_pct}%)")
    return bid

# Verwendung
bid = smart_spot_bid(server_id=142, premium_pct=10)
if bid:
    order = client.create_order(
        server_id=142,
        image="cloreai/ubuntu22.04-cuda12",
        type="spot",
        currency="bitcoin",
        spot_price=bid
    )
```

***

## Wallet-Operationen

### Kontostände prüfen

```python
wallets = client.wallets()
for w in wallets:
    print(f"{w.name}: {w.balance:.8f}")
    if w.deposit:
        print(f"  Einzahlungsadresse: {w.deposit}")
```

### Niedriger Kontostand - Alarm

```python
from clore_ai import CloreAI

def check_balance(min_btc=0.001):
    """Warnen, wenn der BTC-Saldo unter dem Schwellenwert liegt."""
    client = CloreAI()
    wallets = client.wallets()

    for w in wallets:
        if w.name.lower() == "bitcoin" and w.balance < min_btc:
            print(f"⚠️  Niedriger BTC-Saldo: {w.balance:.8f} (Mindestbetrag: {min_btc})")
            return False

    print("✅ Salden OK")
    return True

check_balance(min_btc=0.001)
```

***

## Beste Praktiken zur Fehlerbehandlung

### Ausnahme-Hierarchie

```
CloreAPIError (Basis)
├── DBError           (Code 1) — Datenbankfehler
├── InvalidInputError (Code 2) — ungültige Eingabe
├── AuthError         (Code 3) — ungültiger API-Schlüssel
├── InvalidEndpointError (Code 4) — falscher Endpunkt
├── RateLimitError    (Code 5) — rate-limitiert (wird automatisch erneut versucht)
└── FieldError        (Code 6) — feldspezifischer Fehler
```

### Grundlegende Fehlerbehandlung

```python
from clore_ai import CloreAI
from clore_ai.exceptions import (
    CloreAPIError,
    AuthError,
    RateLimitError,
    InvalidInputError
)

client = CloreAI()

try:
    order = client.create_order(
        server_id=999999,
        image="cloreai/ubuntu22.04-cuda12",
        type="on-demand",
        currency="bitcoin"
    )
except AuthError:
    print("Ungültiger API-Schlüssel — überprüfen Sie CLORE_API_KEY")
except InvalidInputError as e:
    print(f"Ungültige Eingabe: {e}")
except RateLimitError:
    print("Rate-limitiert — das SDK versucht automatisch erneut, aber die maximale Anzahl an Wiederholungen wurde überschritten")
except CloreAPIError as e:
    print(f"API-Fehler (Code {e.code}): {e}")
```

### Retry-Muster mit Backoff

Das SDK verfügt über eingebaute Wiederholungsversuche für Rate-Limits und Netzwerkfehler (`max_retries=3`). Für Anwendungs-Levels-Wiederholungen:

```python
import time
from clore_ai import CloreAI
from clore_ai.exceptions import CloreAPIError, RateLimitError

def retry_operation(func, max_attempts=3, base_delay=2.0):
    """Wiederholen einer Clore-API-Operation mit exponentiellem Backoff."""
    for attempt in range(max_attempts):
        try:
            return func()
        except RateLimitError:
            if attempt < max_attempts - 1:
                delay = base_delay * (2 ** attempt)
                print(f"Rate-limitiert, erneuter Versuch in {delay}s...")
                time.sleep(delay)
            else:
                raise
        except CloreAPIError as e:
            if e.code in (1,):  # DB-Fehler können vorübergehend sein
                if attempt < max_attempts - 1:
                    time.sleep(base_delay)
                    continue
            raise

# Verwendung
client = CloreAI()
servers = retry_operation(lambda: client.marketplace(gpu="RTX 4090"))
```

***

## Performance-Tipps

### 1. Den Client wiederverwenden

```python
# ❌ Schlecht — erstellt jedes Mal eine neue HTTP-Verbindung
for _ in range(10):
    client = CloreAI()
    client.marketplace()
    client.close()

# ✅ Gut — verwendet die HTTP-Verbindung wieder
client = CloreAI()
for _ in range(10):
    client.marketplace()
client.close()
```

### 2. Verwenden Sie Async für gleichzeitige Vorgänge

```python
import asyncio
from clore_ai import AsyncCloreAI

async def compare_gpus():
    async with AsyncCloreAI() as client:
        # Führen Sie 3 Suchanfragen gleichzeitig aus
        rtx4090, rtx3090, a100 = await asyncio.gather(
            client.marketplace(gpu="RTX 4090"),
            client.marketplace(gpu="RTX 3090"),
            client.marketplace(gpu="A100"),
        )

        print(f"RTX 4090: {len(rtx4090)} Server")
        print(f"RTX 3090: {len(rtx3090)} Server")
        print(f"A100: {len(a100)} Server")

asyncio.run(compare_gpus())
```

### 3. Asynchrone Batch-Erstellung von Orders

```python
import asyncio
from clore_ai import AsyncCloreAI

async def batch_deploy(server_ids):
    async with AsyncCloreAI() as client:
        tasks = [
            client.create_order(
                server_id=sid,
                image="cloreai/ubuntu22.04-cuda12",
                type="on-demand",
                currency="bitcoin",
                ssh_password="BatchPass123",
                ports={"22": "tcp"}
            )
            for sid in server_ids
        ]
        orders = await asyncio.gather(*tasks, return_exceptions=True)

        for sid, result in zip(server_ids, orders):
            if isinstance(result, Exception):
                print(f"Server {sid}: FEHLGESCHLAGEN — {result}")
            else:
                print(f"Server {sid}: Order {result.id} erstellt")

        return orders

# Auf 3 Servern gleichzeitig bereitstellen
asyncio.run(batch_deploy([142, 305, 891]))
```

{% hint style="warning" %}
**Hinweis:** Das SDK erzwingt einen 5-Sekunden-Cooldown zwischen `create_order` Aufrufen. Selbst im Async-Modus werden Orders zeitlich gestreckt, um Rate-Limits zu respektieren.
{% endhint %}

### 4. Clients nach Gebrauch schließen

```python
# Der Context-Manager übernimmt dies automatisch
with CloreAI() as client:
    # Arbeit...
    pass  # client.close() wird automatisch aufgerufen

# Oder manuell schließen
client = CloreAI()
try:
    # Arbeit...
    pass
finally:
    client.close()
```

***

## Vollständiges Beispiel: Auto-Scaling von GPU-Workern

```python
import asyncio
import time
from clore_ai import AsyncCloreAI
from clore_ai.exceptions import CloreAPIError

async def auto_scale(
    gpu_model="RTX 4090",
    max_price=2.0,
    target_workers=3,
    image="cloreai/ubuntu22.04-cuda12"
):
    """Einen Pool von GPU-Workern aufrechterhalten."""
    async with AsyncCloreAI() as client:
        # 1. Aktuelle Orders prüfen
        current_orders = await client.my_orders()
        active_count = len(current_orders)
        print(f"Aktive Worker: {active_count}/{target_workers}")

        if active_count >= target_workers:
            print("Bereits Ziel erreicht. Nichts zu tun.")
            return

        # 2. Verfügbare Server finden
        servers = await client.marketplace(gpu=gpu_model, max_price_usd=max_price)
        servers.sort(key=lambda s: s.price_usd or float("inf"))

        needed = target_workers - active_count
        candidates = servers[:needed]

        if len(candidates) < needed:
            print(f"Only {len(candidates)} servers available (need {needed})")

        # 3. Deploy
        for server in candidates:
            try:
                order = await client.create_order(
                    server_id=server.id,
                    image=image,
                    type="on-demand",
                    currency="bitcoin",
                    ssh_password="WorkerPass123",
                    ports={"22": "tcp"}
                )
                print(f"Deployed on server {server.id} → order {order.id}")
            except CloreAPIError as e:
                print(f"Failed to deploy on {server.id}: {e}")

asyncio.run(auto_scale())
```

***

## Nächste Schritte

* [CLI-Automatisierung](/guides/guides_v2-de/erweitert/cli-automation.md) — Bash-Skripte, CI/CD, Batch-Operationen
* [Batch-Verarbeitung](/guides/guides_v2-de/erweitert/batch-processing.md) — Verarbeiten großer Workloads auf Clore-GPUs
* [API-Integration](/guides/guides_v2-de/erweitert/api-integration.md) — Verbinden Sie KI-Dienste mit Ihren Apps


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-de/erweitert/python-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
