---
{
  "title": "Python FHIR SDK: Apps entwickeln mit Type Schema",
  "description": "Ein modernes Python SDK für FHIR, aufgebaut auf Type Schema. Starke Typisierung, Autovervollständigung und ein reibungsloser Weg von FHIR-Ressourcen zu Python-Datenklassen.",
  "date": "2025-06-12",
  "author": "Aleksandr Penskoi",
  "reading-time": "7 minutes",
  "tags": [
    "FHIR Tools",
    "Code Generation",
    "Python"
  ]
}
---
# Type Schema: Python SDK für FHIR

> **Aktualisierung:** Dieser Artikel beschreibt den ursprünglichen MVP auf Basis von fhir-schema-codegen. Das Python SDK ist seitdem zu [`@atomic-ehr/codegen`](https://github.com/atomic-ehr/codegen) migriert worden – mit wesentlichen Verbesserungen: Tree Shaking, polymorphe Bundles, primitive Erweiterungen, fhirpy-Integration und mehr. Siehe den aktualisierten Beitrag: [@atomic-ehr/codegen: Python FHIR Types](https://www.health-samurai.io/articles/atomic-ehr-codegen-python-fhir-types).

Wir haben kürzlich [Type Schema](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk) vorgestellt – einen neuen, sprachagnostischen Ansatz zur Erstellung von SDKs aus FHIR-Paketen. Heute werfen wir einen Blick auf unseren Python SDK MVP und zeigen, wie er die [FHIR-Entwicklung](/articles/using-fhir-to-simplify-healthcare-application-development) von der ersten Installation bis zu einer exzellenten Entwicklererfahrung vereinfacht. Da das SDK automatisch stark typisierte Modelle und praktische Client-Hilfsfunktionen generiert, entfallen stundenlanger Boilerplate-Code und manuelle Schema-Arbeit. Das Ergebnis: Teams können an einem einzigen Nachmittag vom Konzept zu einem FHIR-konformen Prototypen gelangen, ohne sich tief in die FHIR-Spezifikation einarbeiten zu müssen.

In diesem Beitrag erfahren Sie:
- Wie Sie ein Python SDK für beliebige FHIR-Pakete generieren
- Wie das SDK in der Praxis funktioniert, mit Typprüfung und Fehlerbehandlung
- Welche Möglichkeiten es gibt, das SDK für Ihre eigenen Projekte anzupassen

## Python FHIR SDK – Überblick
Unser Python SDK besteht aus zwei Hauptteilen:
- Operationen – Methoden für Erstellen, Lesen, Aktualisieren, Löschen und Suchen
- Ressourcen und Datentypen – Klassen wie Patient, Encounter und Marital Status Code.

Für diesen MVP haben wir uns hauptsächlich auf Ressourcendefinitionen konzentriert und nur grundlegende Unterstützung für Operationen implementiert.

Aufgebaut auf [Pydantic](https://docs.pydantic.dev/latest/), bietet das SDK zuverlässige Validierung und JSON-zu-Python-Konvertierung und lässt sich gut in Python integrieren.

## SDK für Ihr FHIR-Paket generieren
- Installieren Sie unseren Generator:


```javascript
$ npm install -g @fhirschema/codegen
```

- Führen Sie den Python SDK Generator aus:


```javascript
$ npx fscg generate -g python -p hl7.fhir.r4.core@4.0.1 -o my-python-project --py-sdk-package aidbox
```


wobei:
- `-p hl7.fhir.r4.core@4.0.1` – das zu verwendende FHIR-Paket
- `-o my-python-project` – das Zielverzeichnis für Ihr Python-Projekt
- `--py-sdk-package aidbox` – der Name Ihres SDK-Pakets (der gesamte generierte Code wird unter my-python-project/aidbox abgelegt).

Das war es – Sie verfügen nun über ein einsatzbereites Python SDK für [FHIR R4](/articles/fhir-r4-vs-fhir-r5-choosing-the-right-version-for-your-implementation).

## Kein FHIR-Server? In 2 Minuten einen starten
Führen Sie die folgenden Schritte aus:

1. Starten Sie den Aidbox FHIR Server:


```javascript
$ curl -JO https://aidbox.app/runme/sdk && docker compose up --wait
```


2. Aidbox-Lizenz erhalten (nur beim ersten Mal): 

- Öffnen Sie [http://localhost:8080](http://localhost:8080/)
- Folgen Sie den Einrichtungsanweisungen in Ihrem Browser
- Entnehmen Sie das Client-Secret aus der Umgebungsvariablen `BOX_ROOT_CLIENT_SECRET` in der `docker-compose.yml` und verwenden Sie es bei der Client-Initialisierung.

## Verbindung zum FHIR-Server herstellen
Bevor Sie mit dem SDK arbeiten, installieren Sie die erforderlichen Python-Abhängigkeiten. Dies erfolgt mit folgendem Befehl:


```javascript
$ cd my-python-project
$ pip install -r my-python-project/aidbox/requirements.txt
```


Um mit einem FHIR-Server über unser SDK zu arbeiten, müssen Sie einen Client einrichten:


```javascript
from aidbox.client import Client, Auth, AuthCredentials

client = Client(
    base_url="http://localhost:8080/fhir",
    auth=Auth(
        method="basic",
        credentials=AuthCredentials(
            username="root",
            password="secret", # don't forget to update
        ),
    ),
)
```


Anschließend können Sie die Client-Methoden für CRUD-Operationen verwenden: `client.create`, `client.read`, `client.update`, `client.delete` und `client.search`.

## FHIR-Ressourcen erstellen und verarbeiten
Erstellen wir eine Patient-Ressource:
- Importieren Sie die benötigten Klassen und erstellen Sie einen Patienten:


```javascript
from aidbox.hl7_fhir_r4_core import Patient, HumanName, Identifier
patient = Patient(
    identifier=[Identifier(system="http://org.io/id", value="0000-0000")],
    name=[HumanName(given=["John"], family="Doe")],
    gender="male",
)
```

- Speichern Sie den Patienten auf dem Server und sehen Sie sich die Ergebnisse an:


```javascript
result = client.create(patient)
print(result.to_json(indent=2))
from pprint import pprint
pprint(result.model_dump(exclude_unset=True, exclude_none=True))
```



```javascript
{
  "resourceType": "Patient",
  "id": "859316db-8428-40ae-9a63-c2cbe088f540",
  "meta": {
    "extension": [
      {
        "url": "https://aidbox.app/ex/createdAt",
        "valueInstant": "2025-06-06T11:07:47.062435Z"
      }
    ],
    "lastUpdated": "2025-06-06T11:07:47.062435Z",
    "versionId": "195"
  },
  "gender": "male",
  "identifier": [
    {
      "system": "http://org.io/id",
      "value": "0000-0000"
    }
  ],
  "name": [
    {
      "family": "Doe",
      "given": [
        "John"
      ]
    }
  ]
}
```



```javascript
{'gender': 'male',
 'id': '859316db-8428-40ae-9a63-c2cbe088f540',
 'identifier': [{'system': 'http://org.io/id', 'value': '0000-0000'}],
 'meta': {'extension': [{'url': 'https://aidbox.app/ex/createdAt',
                         'valueInstant': '2025-06-06T11:07:47.062435Z'}],
          'lastUpdated': '2025-06-06T11:07:47.062435Z',
          'versionId': '195'},
 'name': [{'family': 'Doe', 'given': ['John']}],
 'resourceType': 'Patient'}
```


Das vollständige Beispiel finden Sie hier: [example/python/main.py](https://github.com/fhir-schema/fhir-schema-codegen/blob/main/example/python/main.py).

## Fehlerbehandlung mit Typprüfung und Laufzeitvalidierung
Was passiert, wenn wir einen Fehler machen? Versuchen wir, ein falsches Feld und einen falschen Wert hinzuzufügen:


```javascript
Patient(
    name=[HumanName(family="Doe")],
    gender="FOO",            # wrong value
    some_data="1990-01-01",  # wrong field
)
```


Zunächst prüfen wir dies statisch. Wir können dafür mypy verwenden, müssen jedoch das pydantic.mypy-Plugin in der mypy.ini aktivieren:


```javascript
[mypy]
plugins = pydantic.mypy
```


Jetzt können wir `mypy` zur Überprüfung unseres Codes ausführen:


```javascript
$ mypy . --strict
main.py:59: error: Unexpected keyword argument "some_data" for "Patient"  [call-arg]
Found 1 error in 1 file (checked 155 source files)
```


Wir erhalten einen statischen Typfehler – für Python gar nicht schlecht!

Nun schauen wir, was bei der Ausführung passiert:


```javascript
$ python main.py
Traceback (most recent call last):
  File "/fhir-schema-codegen/example/python/main.py", line 59, in <module>
    Patient(
    ~~~~~~~^
        name=[HumanName(family="Doe")],
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        gender="FOO",  # wrong value
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        some_data="1990-01-01",  # wrong field
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/fhir-schema-codegen/example/python/venv/lib/python3.13/site-packages/pydantic/main.py", line 253, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 2 validation errors for Patient
gender
  Input should be 'male', 'female', 'other' or 'unknown' [type=literal_error, input_value='FOO', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/literal_error
some_data
  Extra inputs are not permitted [type=extra_forbidden, input_value='1990-01-01', input_type=str]
    For further information visit https://errors.pydantic.dev/2.11/v/extra_forbidden
```


Wir sehen nun beide Fehler mit hilfreichen Meldungen:
- Die genaue Codezeile, die den Fehler ausgelöst hat
- Den Fehler im Feld `gender`: was angegeben wurde ('FOO') und was erwartet wird
- Den Fehler im Feld `some_data`: zusätzliche Felder sind nicht erlaubt

Sehr praktisch!

## Das SDK anpassen
Hier sind einige Möglichkeiten, das Python SDK anzupassen:

### Mit nicht-standardisierten Ressourcen arbeiten
Angenommen, Ihre Daten enthalten zusätzliche Attribute, wie etwa ein Patient mit einer lotteryNumber:


```javascript
>>> patient_json = """
... {
...   "resourceType": "Patient",
...   "name": [ { "family": "Doe", "given": [ "John" ] } ],
...   "lotteryNumber": 123456
... }
... """
... patient = Patient.from_json(patient_json)
...
pydantic_core._pydantic_core.ValidationError: 1 validation error for Patient
lotteryNumber
  Extra inputs are not permitted [type=extra_forbidden, input_value=123456, input_type=int]
    For further information visit https://errors.pydantic.dev/2.11/v/extra_forbidden
```


Standardmäßig lehnt das SDK dies ab. Um das zu beheben, fügen Sie beim Generieren das Flag `--py-allow-extra-fields` hinzu:


```javascript
$ npx fscg generate -g python -p hl7.fhir.r4.core@4.0.1 -o my-python-project --py-sdk-package aidbox --py-allow-extra-fields
```


Nun können Sie:
- JSON mit zusätzlichen Feldern parsen
- Es ohne die zusätzlichen Felder an den FHIR-Server senden
- Auf die zusätzlichen Felder in Ihrem Code zugreifen


```javascript
>>> p = Patient.from_json(patient_json)
>>> p.to_json()
{'resourceType': 'Patient', 'name': [{'family': 'Doe', 'given': ['John']}]}
>>> p.model_extra
{'lotteryNumber': 123456}
```


Hinweis: Dies verdeutlicht, warum Code-Generierung einem universellen SDK vorzuziehen ist. Durch Generierung lässt sich einfacher, zweckorientierter Code erzeugen, der leicht lesbar ist. Ein universelles SDK würde deutlich komplexeren Code erfordern.

### Unterstützung für benutzerdefinierte Ressourcen hinzufügen
Das Erstellen benutzerdefinierter FHIR-Ressourcen sollte genauso unkompliziert sein wie die Verwendung der Standardressourcen. Fügen Sie einfach Ihre benutzerdefinierte Ressource dem Generierungsprozess hinzu.

Betrachten wir ein Health Samurai-Beispiel für benutzerdefinierte Ressourcen: [Aidbox Notify via Custom Resources](https://github.com/Aidbox/examples/tree/main/aidbox-features/aidbox-notify-via-custom-resources).

In diesem Demo-Projekt definieren wir benutzerdefinierte Ressourcen per [FHIR Schema](https://github.com/fhir-schema/fhir-schema): `TutorNotificationTemplate` und `TutorNotification`. Wir können sie als JSON-Dateien speichern und dem SDK-Generator übergeben:


```javascript
npx fscg generate -g python -p hl7.fhir.r4.core@4.0.1 \
    --fhir-schema example/custom_resources/TutorNotification.fs.json \
    --fhir-schema example/custom_resources/TutorNotificationTemplate.fs.json \
    --py-sdk-package aidbox -o $(PYTHON_SDK_EXAMPLE)
```


In der Ausgabe finden wir den generierten Code für diese Ressourcen, zum Beispiel:


```javascript
class TutorNotificationTemplate(DomainResource):
    model_config = ConfigDict(validate_by_name=True, serialize_by_alias=True, extra="forbid")

    resource_type: str = Field(
        default='TutorNotificationTemplate',
        alias='resourceType',
        serialization_alias='resourceType',
        frozen=True,
        pattern='TutorNotificationTemplate'
    )

    template: str | None = Field(None, alias="template", serialization_alias="template")

    def to_json(self, indent: int | None = None) -> str:
        return self.model_dump_json(exclude_unset=True, exclude_none=True, indent=indent)

    @classmethod
    def from_json(cls, json: str) -> TutorNotificationTemplate:
        return cls.model_validate_json(json)
```


So lässt sich das SDK exakt an Ihre spezifischen Anforderungen anpassen.

Hinweis: Ein weiterer Vorteil der Code-Generierung sind vereinfachte Upgrades. Wenn Sie zu einer neuen FHIR-Version wechseln müssen, genügt es, das SDK neu zu generieren. Ihre IDE hebt dann automatisch alle Stellen hervor, an denen Sie Ihren Code anpassen müssen. Das ist wesentlich einfacher als die Anpassung eines universellen SDKs.

## Das SDK modifizieren
Möchten Sie das Verhalten des SDKs ändern? Unsere Generatoren sind Open Source, sodass Sie sie anpassen können. Wenn Sie beispielsweise nur FHIR-Daten verarbeiten und keine Serververbindung benötigen, können Sie den Client-Code entfernen.

Dafür gibt es drei Möglichkeiten:
- **Manuell**: Löschen Sie einfach die nicht benötigten Dateien nach der Generierung
- **Generator anpassen**: 
Forken Sie [fhir-schema-codegen](https://github.com/fhir-schema/fhir-schema-codegen/tree/main)
- Öffnen Sie src/generators/python/index.ts
- Suchen Sie die generate-Methode
- Entfernen Sie die Zeile mit this.copyStaticFiles()
- Sie haben nun einen Generator, der ausschließlich Typdefinitionen erzeugt

- **Beitragen**. Fügen Sie dem Generator ein CLI-Flag wie `--py-only-type` hinzu und reichen Sie einen PR ein.

## Bereit zum Entwickeln?
Wir haben gezeigt, wie Sie unser Python SDK für FHIR generieren und verwenden. Der Code funktioniert mit statischer Typprüfung und bietet hervorragende IDE-Unterstützung.

Erkunden Sie das [Python SDK Beispiel](https://github.com/fhir-schema/fhir-schema-codegen/tree/main/example/python) und sehen Sie sich [test_sdk.py](https://github.com/fhir-schema/fhir-schema-codegen/blob/main/example/python/test_sdk.py) für weitere Client-Methoden an.

*Generator-Quellcode:*[ GitHub – fhir‑schema‑codegen
](https://github.com/fhir-schema/fhir-schema-codegen)*[Type Schema](/blog/type-schema-a-pragmatic-approach-to-build-fhir-sdk)-Spezifikation:*[ GitHub – type‑schema](https://github.com//fhir-clj/type-schema)

Treten Sie mit mir – [Aleksandr Penskoi](https://www.linkedin.com/in/aleksandr-penskoi/) – auf LinkedIn in Kontakt, um Ihre spezifischen Anforderungen zu besprechen, oder besuchen Sie uns im [Type Schema Zulip Channel](https://chat.fhir.org/#narrow/channel/498057-Type-Schema).

Siehe auch: [FHIR in dynamischen Sprachen implementieren](/blog/implementing-fhir-in-dynamic-languages).