---
{
  "title": "SDK de Python para FHIR: desarrolle aplicaciones con Type Schema",
  "description": "Un SDK moderno de Python para FHIR construido sobre Type Schema. Tipado fuerte, autocompletado y un camino fluido desde los recursos FHIR hasta las clases de datos de Python.",
  "date": "2025-06-12",
  "author": "Aleksandr Penskoi",
  "reading-time": "7 minutes",
  "tags": [
    "FHIR Tools",
    "Code Generation",
    "Python"
  ]
}
---

> For the complete documentation index, see [llms.txt](https://www.health-samurai.io/llms.txt).
> Use it to discover all available pages before guessing URLs.

---
# Type Schema: SDK de Python para FHIR

> **Actualización:** Este artículo describe el MVP original basado en fhir-schema-codegen. El SDK de Python se ha trasladado a [`@atomic-ehr/codegen`](https://github.com/atomic-ehr/codegen) con mejoras significativas: tree shaking, bundles polimórficos, extensiones primitivas, integración con fhirpy y más. Consulte la publicación actualizada: [@atomic-ehr/codegen: Python FHIR Types](https://www.health-samurai.io/articles/atomic-ehr-codegen-python-fhir-types).

Recientemente anunciamos [Type Schema](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk)—una nueva forma independiente del lenguaje para construir SDKs a partir de paquetes FHIR. Hoy veremos nuestro MVP del SDK de Python y mostraremos cómo agiliza el [desarrollo con FHIR](/articles/using-fhir-to-simplify-healthcare-application-development) desde la primera instalación hasta una excelente experiencia de desarrollo. Al generar automáticamente modelos con tipado fuerte y útiles funciones auxiliares de cliente, el SDK elimina horas de código repetitivo y de manipulación manual de esquemas. En resumen: los equipos pueden pasar de un concepto a un prototipo conforme a FHIR en una sola tarde, sin necesidad de profundizar en la especificación FHIR.

En esta publicación usted:
- Aprenderá a generar un SDK de Python para cualquier paquete FHIR
- Verá el SDK en acción, con comprobación de tipos y gestión de errores
- Descubrirá opciones para personalizar el SDK en sus propios proyectos

## Descripción general del SDK de Python para FHIR
Nuestro SDK de Python tiene dos partes principales:
- Operaciones: métodos para las funciones de creación, lectura, actualización, eliminación y búsqueda
- Recursos y tipos de datos: clases como Patient, Encounter y Marital Status Code.

Para este MVP, nos centramos principalmente en las definiciones de recursos, manteniendo un soporte básico para las operaciones.

Construido sobre [Pydantic](https://docs.pydantic.dev/latest/), el SDK ofrece una buena validación y conversión de JSON a Python, y funciona bien con Python.

## Genere el SDK para su paquete FHIR
- Instale nuestro generador:


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

- Ejecute el generador del SDK de Python:


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


donde:
- `-p hl7.fhir.r4.core@4.0.1`—el paquete FHIR que se utilizará
- `-o my-python-project`—dónde colocar su proyecto Python
- `--py-sdk-package aidbox`—el nombre de su paquete SDK (todo el código generado irá en my-python-project/aidbox).

Eso es todo: ahora dispone de un SDK de Python listo para usar con [FHIR R4](/articles/fhir-r4-vs-fhir-r5-choosing-the-right-version-for-your-implementation).

## ¿No tiene servidor FHIR? Ponga uno en marcha en 2 minutos
Siga estos pasos:

1. Inicie el servidor FHIR Aidbox:


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


2. Obtenga una licencia de Aidbox (solo la primera vez): 

- Abra [http://localhost:8080](http://localhost:8080/)
- Siga las instrucciones de configuración en su navegador
- Obtenga el secreto de cliente de la variable de entorno `BOX_ROOT_CLIENT_SECRET` del archivo `docker-compose.yml` y utilícelo en la inicialización del cliente.

## Conéctese al servidor FHIR
Antes de empezar a trabajar con el SDK, instale las dependencias de Python necesarias. Puede hacerlo ejecutando:


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


Para trabajar con un servidor FHIR mediante nuestro SDK, necesita configurar un cliente:


```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
        ),
    ),
)
```


Después podrá usar los métodos del cliente para operaciones CRUD: `client.create`, `client.read`, `client.update`, `client.delete` y `client.search`.

## Cree y procese recursos FHIR
Vamos a crear un recurso Patient:
- Importe las clases que necesita y cree un Patient:


```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",
)
```

- Guárdelo en el servidor y vea los resultados:


```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'}
```


El ejemplo completo está disponible aquí: [example/python/main.py](https://github.com/fhir-schema/fhir-schema-codegen/blob/main/example/python/main.py).

## Gestión de errores con comprobación de tipos y validación en tiempo de ejecución
¿Qué ocurre si cometemos un error? Intentemos añadir un campo y un valor incorrectos:


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


Primero, comprobemos los tipos. Podemos usar mypy para ello, pero necesitamos habilitar el plugin pydantic.mypy en mypy.ini:


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


Ahora podemos ejecutar `mypy` para comprobar nuestro código:


```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)
```


Obtenemos un error de tipo estático: ¡nada mal para Python!

Ahora veamos qué ocurre cuando lo ejecutamos:


```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
```


Ahora vemos ambos errores con mensajes informativos:
- El código exacto que generó el error
- El error del campo `gender`: lo que proporcionamos ('FOO') y lo que debería ser
- El error del campo `some_data`: no se permiten campos adicionales

¡Bastante útil!

## Personalización del SDK
A continuación se presentan algunas formas de personalizar el SDK de Python:

### Trabajo con recursos no estándar
Suponga que sus datos incluyen atributos adicionales, como un Patient con un 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
```


Por defecto, el SDK rechaza esto. Para solucionarlo, añada el indicador `--py-allow-extra-fields` al generar:


```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
```


Ahora puede:
- Analizar JSON que contenga campos adicionales
- Enviarlo al servidor FHIR sin los campos adicionales
- Acceder a los campos adicionales en su código


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


Nota: Esto ilustra por qué la generación de código es mejor que un SDK universal. Con la generación, podemos crear código sencillo y de propósito específico que resulta fácil de leer. Un SDK universal requeriría un código mucho más complejo.

### Añada soporte para recursos personalizados
Crear recursos FHIR personalizados debería ser igual de sencillo que usar los estándar. Simplemente añada su recurso personalizado al proceso de generación.

Veamos un ejemplo de recurso personalizado de Health Samurai: [Aidbox Notify via Custom Resources](https://github.com/Aidbox/examples/tree/main/aidbox-features/aidbox-notify-via-custom-resources).

En este proyecto de demostración, definimos recursos personalizados mediante [FHIR Schema](https://github.com/fhir-schema/fhir-schema): `TutorNotificationTemplate` y `TutorNotification`. Podemos guardarlos como archivos JSON y pasarlos al generador del SDK:


```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)
```


Y en la salida encontraremos el código generado para estos recursos, como:


```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)
```


Esto le permite adaptar el SDK a sus necesidades específicas.

Nota: Otra ventaja de la generación de código es la facilidad de actualización. Si necesita migrar a una nueva versión de FHIR, simplemente regenere el SDK. Su IDE resaltará todos los lugares donde necesita actualizar el código. Esto es mucho más sencillo que intentar adaptar un SDK universal.

## Personalización del SDK
¿Necesita cambiar el funcionamiento del SDK? Nuestros generadores son de código abierto, por lo que puede personalizarlos. Por ejemplo, si solo necesita procesar datos FHIR y no requiere conexión a un servidor, puede eliminar el código del cliente.

Hay tres formas de hacerlo:
- **Manual**: Simplemente elimine los archivos que no necesite después de la generación
- **Modificar el generador**: 
Haga un fork de [fhir-schema-codegen](https://github.com/fhir-schema/fhir-schema-codegen/tree/main)
- Abra src/generators/python/index.ts
- Localice el método generate
- Elimine la línea con this.copyStaticFiles()
- Ahora dispone de un generador que solo crea definiciones de tipos

- **Contribuir**. Añada un indicador de línea de comandos como `--py-only-type` al generador y envíe un PR.

## ¿Listo para desarrollar?
Hemos mostrado cómo generar y utilizar nuestro SDK de Python para FHIR. El código funciona con comprobación estática de tipos y le ofrece un excelente soporte de IDE.

Explore el [ejemplo del SDK de Python](https://github.com/fhir-schema/fhir-schema-codegen/tree/main/example/python) y consulte [test_sdk.py](https://github.com/fhir-schema/fhir-schema-codegen/blob/main/example/python/test_sdk.py) para conocer métodos adicionales del cliente.

*Código fuente del generador:*[ GitHub – fhir‑schema‑codegen
](https://github.com/fhir-schema/fhir-schema-codegen)*Especificación de [Type Schema](/blog/type-schema-a-pragmatic-approach-to-build-fhir-sdk):*[ GitHub – type‑schema](https://github.com//fhir-clj/type-schema)

Conéctese conmigo—[Aleksandr Penskoi](https://www.linkedin.com/in/aleksandr-penskoi/)—en LinkedIn para hablar sobre sus necesidades específicas, o únase a nosotros en el [canal de Zulip de Type Schema](https://chat.fhir.org/#narrow/channel/498057-Type-Schema).

Véase también: [Implementación de FHIR en lenguajes dinámicos](/blog/implementing-fhir-in-dynamic-languages).