Type Schema : SDK Python pour FHIR
Mise à jour : Cet article décrit le premier MVP fondé sur fhir-schema-codegen. Le SDK Python a depuis migré vers
@atomic-ehr/codegen, avec des améliorations importantes — tree shaking, bundles polymorphes, extensions primitives, intégration fhirpy, et plus encore. Consultez l'article mis à jour : @atomic-ehr/codegen: Python FHIR Types.
Nous avons récemment annoncé Type Schema — une nouvelle façon indépendante du langage de construire des SDK à partir de paquets FHIR. Aujourd'hui, examinons notre MVP de SDK Python et voyons comment il simplifie le développement FHIR, de la première installation jusqu'à une excellente expérience développeur. Parce qu'il génère automatiquement des modèles fortement typés et des assistants client pratiques, le SDK élimine des heures de code générique et de manipulation manuelle de schémas. En bref : les équipes peuvent passer d'un concept à un prototype conforme à FHIR en une seule après-midi, sans plonger profondément dans la spécification FHIR.
Dans cet article, vous allez :
- Apprendre à générer un SDK Python pour n'importe quel paquet FHIR
- Voir le SDK en action, avec la vérification de types et la gestion des erreurs
- Découvrir des options pour personnaliser le SDK selon vos propres projets
Aperçu du SDK Python pour FHIR
Notre SDK Python comporte deux parties principales :
- Les opérations — méthodes pour les fonctions de création, lecture, mise à jour, suppression et recherche
- Les ressources et types de données — classes telles que Patient, Encounter et Marital Status Code.
Pour ce MVP, nous nous sommes concentrés principalement sur les définitions de ressources, en conservant un support de base pour les opérations.
Fondé sur Pydantic, le SDK offre une bonne validation et une conversion JSON vers Python, et fonctionne bien avec Python.
Générer un SDK pour votre paquet FHIR
- Installez notre générateur :
$ npm install -g @fhirschema/codegen
- Exécutez le générateur de SDK Python :
$ npx fscg generate -g python -p hl7.fhir.r4.core@4.0.1 -o my-python-project --py-sdk-package aidbox
où :
-p hl7.fhir.r4.core@4.0.1— le paquet FHIR à utiliser-o my-python-project— où placer votre projet Python--py-sdk-package aidbox— le nom de votre paquet SDK (tout le code généré ira dans my-python-project/aidbox).
C'est tout — vous disposez maintenant d'un SDK Python prêt à l'emploi pour FHIR R4.
Pas de serveur FHIR? Démarrez-en un en 2 minutes
Suivez ces étapes :
- Démarrez le serveur FHIR Aidbox :
$ curl -JO https://aidbox.app/runme/sdk && docker compose up --wait
- Obtenez une licence Aidbox (première fois seulement) :
- Ouvrez http://localhost:8080
- Suivez les instructions de configuration dans votre navigateur
- Obtenez le secret client depuis la variable d'environnement
BOX_ROOT_CLIENT_SECRETdansdocker-compose.ymlet utilisez-le lors de l'initialisation du client.
Se connecter au serveur FHIR
Avant de commencer à utiliser le SDK, installez les dépendances Python requises. Vous pouvez le faire en exécutant :
$ cd my-python-project
$ pip install -r my-python-project/aidbox/requirements.txt
Pour travailler avec un serveur FHIR à l'aide de notre SDK, vous devez configurer un client :
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
),
),
)
Après cela, vous pouvez utiliser les méthodes du client pour les opérations CRUD : client.create, client.read, client.update, client.delete et client.search.
Créer et traiter des ressources FHIR
Créons une ressource Patient :
- Importez les classes dont vous avez besoin et créez un Patient :
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",
)
- Sauvegardez-le sur le serveur et consultez les résultats :
result = client.create(patient)
print(result.to_json(indent=2))
from pprint import pprint
pprint(result.model_dump(exclude_unset=True, exclude_none=True))
{
"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"
]
}
]
}
{'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'}
L'exemple complet est disponible ici : example/python/main.py.
Gestion des erreurs avec vérification de types et validation à l'exécution
Et si nous faisions une erreur? Essayons d'ajouter un champ et une valeur incorrects :
Patient(
name=[HumanName(family="Doe")],
gender="FOO", # wrong value
some_data="1990-01-01", # wrong field
)
D'abord, vérifions les types. Nous pouvons utiliser mypy pour cela, mais nous devons activer le plugin pydantic.mypy dans mypy.ini :
[mypy]
plugins = pydantic.mypy
Maintenant, nous pouvons exécuter mypy pour vérifier notre code :
$ 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)
Nous obtenons une erreur de type statique — pas mal pour Python!
Voyons maintenant ce qui se passe lorsque nous l'exécutons :
$ 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
Nous voyons maintenant les deux erreurs avec des messages utiles :
- Le code exact qui a déclenché l'erreur
- L'erreur du champ
gender: ce que nous avons fourni ('FOO') et ce que ça devrait être - L'erreur du champ
some_data: les champs supplémentaires ne sont pas permis
Plutôt bien!
Personnaliser votre SDK
Voici quelques façons de personnaliser le SDK Python :
Travailler avec des ressources non standard
Supposons que vos données contiennent des attributs supplémentaires, comme un Patient avec un lotteryNumber :
>>> 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
Par défaut, le SDK rejette cela. Pour y remédier, ajoutez l'indicateur --py-allow-extra-fields lors de la génération :
$ 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
Vous pouvez maintenant :
- Analyser du JSON contenant des champs supplémentaires
- L'envoyer au serveur FHIR sans les champs supplémentaires
- Accéder aux champs supplémentaires dans votre code
>>> p = Patient.from_json(patient_json)
>>> p.to_json()
{'resourceType': 'Patient', 'name': [{'family': 'Doe', 'given': ['John']}]}
>>> p.model_extra
{'lotteryNumber': 123456}
Remarque : Cela illustre pourquoi la génération de code est préférable à un SDK universel. Avec la génération, nous pouvons créer du code simple et adapté à un usage précis, facile à lire. Un SDK universel nécessiterait un code beaucoup plus complexe.
Ajouter la prise en charge de ressources personnalisées
Créer des ressources FHIR personnalisées devrait être aussi simple qu'utiliser les ressources standard. Il suffit d'ajouter votre ressource personnalisée au processus de génération.
Regardons un exemple de ressource personnalisée de Health Samurai : Aidbox Notify via Custom Resources.
Dans ce projet de démonstration, nous définissons des ressources personnalisées par FHIR Schema : TutorNotificationTemplate et TutorNotification. Nous pouvons les sauvegarder sous forme de fichiers JSON et les passer au générateur de SDK :
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)
Et dans la sortie, nous trouverons le code généré pour ces ressources, comme :
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)
Cela vous permet d'adapter le SDK à vos besoins spécifiques.
Remarque : Un autre avantage de la génération de code est la facilité de mise à niveau. Si vous devez passer à une nouvelle version de FHIR, vous pouvez simplement régénérer le SDK. Votre environnement de développement intégré mettra alors en évidence tous les endroits où vous devez mettre à jour votre code. C'est bien plus simple que d'essayer d'adapter un SDK universel.
Personnaliser le SDK
Besoin de modifier le fonctionnement du SDK? Nos générateurs sont à code source ouvert, vous pouvez donc les personnaliser. Par exemple, si vous n'avez besoin que de traiter des données FHIR et ne nécessitez pas de connexion à un serveur, vous pouvez supprimer le code client.
Il y a trois façons de procéder :
-
Manuel : Supprimez simplement les fichiers dont vous n'avez pas besoin après la génération
-
Modifier le générateur : Faites une bifurcation de fhir-schema-codegen
-
Ouvrez src/generators/python/index.ts
-
Trouvez la méthode generate
-
Supprimez la ligne avec this.copyStaticFiles()
-
Vous avez maintenant un générateur qui crée uniquement des définitions de types
-
Contribuer. Ajoutez un indicateur CLI comme
--py-only-typeau générateur et soumettez une demande de tirage.
Prêt à construire?
Nous vous avons montré comment générer et utiliser notre SDK Python pour FHIR. Le code fonctionne avec la vérification de types statique et vous offre un excellent support dans votre environnement de développement intégré.
Explorez l'exemple de SDK Python et consultez test_sdk.py pour des méthodes client supplémentaires.
Source du générateur : GitHub – fhir‑schema‑codegen Spécification Type Schema : GitHub – type‑schema
Connectez-vous avec moi — Aleksandr Penskoi — sur LinkedIn pour discuter de vos besoins spécifiques, ou rejoignez-nous sur le canal Zulip Type Schema.
Voir aussi : Implémenter FHIR dans des langages dynamiques.



