Python para Revit: toma el control cuando Dynamo se queda corto
El grafo nació para localizar espacios sin código. Recogía elementos, leía un parámetro y generaba una tabla. Se entendía de izquierda a derecha y cumplía su trabajo. Después llegaron los códigos heredados, las excepciones por fase, dos plantillas con nombres distintos y un Excel que trataba “Sala de reuniones” y “Reunión” como usos diferentes. Dynamo seguía ejecutándose; explicar por qué un espacio terminaba en cada salida ya requería puntero láser.
Python para Revit suele aparecer en ese momento. Permite reunir condiciones, organizar datos y acceder a la API con más control. El movimiento sensato no consiste en esconder el grafo entero dentro de un nodo. Se trata de trasladar la pieza que ha dejado de ser legible y conservar a la vista las entradas, la previsualización y la decisión de escribir en el modelo.
Vamos a seguir el control de espacios durante esa operación. La parte interesante empieza cuando el primer script falla, porque ahí aparecen las diferencias entre los objetos de Dynamo, la API de Revit y los datos que nosotros creíamos tener. Es el tipo de fallo que enseña bastante más que una captura donde todo sale verde.
Tabla de contenidos
El grafo creció porque la realidad tenía más de dos estados
La primera versión distinguía código vacío y código informado. Al incorporar el Excel, esa división dejó de servir. Un espacio podía tener el valor esperado, contener otro distinto, carecer de propuesta o quedar fuera del alcance. También había elementos en fases que no debían revisarse y espacios procedentes de vínculos que el flujo podía consultar, pero no modificar.
Cada caso añadió filtros, ramas y recombinaciones de listas. Ninguno era absurdo por separado. El problema era que la regla principal —decidir qué hacer con cada espacio— se encontraba repartida entre nodos alejados. Si cambiaba la política sobre valores existentes, había que localizar varias zonas y confiar en no olvidar una conexión.
Antes de tocar Python, pusimos nombre a los estados: sin cambios, actualizar, conflicto, omitido y no evaluable. Esa lista hizo visible algo que el grafo ocultaba. Un parámetro ausente no era lo mismo que un valor vacío; un conflicto tampoco debía mezclarse con un error técnico.
La pieza candidata a pasar a código era precisamente esa clasificación. Dynamo seguiría recogiendo espacios, mostrando resultados y permitiendo confirmar. Una función recibiría valores simples —código actual, propuesta, fase y posibilidad de edición— y devolvería estado, motivo y datos necesarios para el informe. El cambio reducía cables, pero sobre todo reunía una decisión que debía leerse entera.
El primer script tropieza con un objeto que parece un espacio
Probamos el nodo Python con un elemento y pedimos una propiedad de la API. Aparece un error: el objeto recibido no expone lo que esperábamos. Dynamo trabaja con envoltorios que facilitan la interacción con sus nodos; la API de Revit utiliza sus propias clases. A simple vista ambos representan el mismo espacio. Para el código, uno todavía lleva abrigo.
Esta frontera explica muchos ejemplos que funcionan al copiarlos en un entorno y fallan en otro. Python es el lenguaje; Dynamo y otros entornos proporcionan el motor, las referencias y el acceso al documento. La documentación técnica muestra importaciones de tipos de Revit y componentes como DocumentManager porque el fragmento necesita saber dónde se está ejecutando.
Reducimos la prueba a una entrada: un espacio, su identificador y su nombre. Inspeccionamos qué tipo llega, obtenemos el elemento interno cuando corresponde y devolvemos una salida que Dynamo puede mostrar. Después entran tres espacios: uno normal, uno procedente de un vínculo y otro que no debería haber pasado el filtro.
El siguiente fallo aparece con las listas. Dynamo entrega varios grupos porque los espacios estaban organizados por nivel, mientras el script esperaba una colección plana. Aplanarlo todo consigue que se ejecute, pero elimina la relación con cada planta. La salida ya no puede explicar de dónde procede un elemento. En lugar de añadir un flatten hasta que desaparezca el error, decidimos qué estructura necesita realmente la regla y preservamos el nivel como dato.
Por último, un espacio sin el parámetro esperado se clasifica como actualizable. La función inicial había convertido el valor ausente en una cadena vacía. Corregimos la lectura para separar “el parámetro existe y está vacío” de “el parámetro no existe”. El segundo caso pasa a no evaluable y señala una diferencia de plantilla que el equipo debe resolver.
La sesión no ha producido todavía un botón espectacular. Ha aclarado qué objetos circulan, qué supuestos eran falsos y qué casos debe rechazar la herramienta. Con eso ya podemos escribir una regla que no dependa de que el modelo se comporte siempre como nuestro archivo de prueba.
La decisión se puede probar sin abrir Revit
La función de clasificación no necesita conocer elementos, documentos ni transacciones. Puede trabajar con valores simples. Esta separación permite comprobar la política del proyecto lejos de la integración.
def decidir_codigo(actual, propuesto, incluido=True, editable=True):
if not incluido:
return {"estado": "omitido", "motivo": "fuera de alcance"}
if not editable:
return {"estado": "omitido", "motivo": "no editable"}
if propuesto is None:
return {"estado": "no_evaluable", "motivo": "sin propuesta"}
if actual and actual != propuesto:
return {
"estado": "conflicto",
"actual": actual,
"propuesto": propuesto
}
if actual == propuesto:
return {"estado": "sin_cambios"}
return {"estado": "actualizar", "valor": propuesto}
Preparamos casos para cada estado y alguno incómodo: propuesta vacía, códigos con espacios, valor duplicado y fase excluida. La normalización de textos ocurre antes de decidir, de modo que “A-01” y “ A-01 ” no generen un conflicto artificial. Si el equipo cambia la política sobre valores existentes, las pruebas muestran exactamente qué comportamiento se modifica.
Alrededor de esta función queda el código que sí depende de Revit: recuperar espacios, localizar el parámetro y convertir valores. Esa frontera reduce la superficie que exige un documento abierto. También evita mezclar una decisión BIM con detalles del entorno, que suelen cambiar por motivos distintos.
La vista previa separa un control útil de una modificación temeraria
El recorrido completo comienza leyendo espacios y el Excel. El flujo valida columnas, normaliza usos y conserva identificadores. Python clasifica cada caso. Dynamo recibe una tabla con elemento, nivel, valor actual, propuesta, estado y motivo. Hasta ese momento el documento permanece intacto.
La persona puede revisar conflictos y confirmar únicamente los casos marcados como actualizar. Esa lista cerrada entra en una transacción, el mecanismo con el que Revit agrupa cambios. Antes de escribir, el script vuelve a comprobar que el elemento y el parámetro existen y siguen siendo editables. Entre la previsualización y la ejecución alguien puede haber sincronizado; la herramienta no debería vivir en un universo donde eso nunca ocurre.
La política de fallo debe estar decidida. Si un espacio no admite el cambio, quizá podamos continuar con el resto y registrarlo. Si los códigos deben actualizarse como conjunto coherente, interesa revertir todo. Ninguna opción es universal. Capturar cualquier excepción y devolver “completado” sí es universalmente mala.
Al cerrar la transacción, el informe compara propuesta y valor realmente escrito. Incluye documento, versión de la regla y momento de ejecución. La tabla deja de ser un residuo del script para convertirse en evidencia de qué se cambió y qué quedó pendiente.
Dynamo mantiene entradas y previsualización. Python concentra la clasificación y el acceso específico; la API realiza cambios bajo las reglas de Revit. El usuario puede seguir el proceso sin abrir el nodo de código, pero ese nodo también puede leerse y probarse sin recorrer todo el grafo.
La segunda persona descubre los requisitos que faltaban
En el ordenador del autor, el Excel correcto, la fase y el documento activo parecían obvios. Fuera de él, la herramienta necesita validar cada uno. Una columna renombrada debe producir un mensaje claro; un identificador duplicado no puede escoger la primera fila; un archivo de otra plantilla debe detenerse antes de abrir una transacción.
El paquete de entrega incluye un modelo mínimo con espacio correcto, parámetro vacío, parámetro ausente, conflicto y elemento no editable. También registra la versión de Revit, el entorno Python y las dependencias. “Funciona con Python” sigue siendo una descripción bastante optimista de compatibilidad.
Si el control se distribuye a muchas personas, quizá llegue el momento de otra interfaz o un complemento. Ese salto añade instalación, versiones y soporte. Tiene sentido cuando la regla es estable y el uso frecuente. Antes, Dynamo continúa siendo un lugar transparente para ajustar el proceso junto al equipo BIM.
También puede ocurrir lo contrario: la plantilla se corrige, el Excel desaparece y la tarea deja de justificar la herramienta. Retirarla es una decisión válida. Mantener automatizaciones por cariño histórico acaba llenando los equipos de botones que nadie se atreve a pulsar.
Python aporta control cuando sabemos qué complejidad estamos moviendo
Nuestro grafo vuelve a contar una historia: recibe espacios y propuestas, muestra estados, permite revisar y modifica solo lo confirmado. Python no ha sustituido a Dynamo. Ha absorbido la decisión que las ramas estaban ocultando y la ha convertido en una función comprobable.
Si un flujo cabe en una pantalla, se entiende y otra persona puede mantenerlo, dejarlo en nodos es una decisión perfectamente técnica. Cuando las excepciones escondan el proceso, habrá una razón real para pasar parte a código. Esa razón —no la sensación de que programar siempre es el siguiente nivel— es lo que hace que Python para Revit merezca la pena.
Respuestas