Experiencia de desarrollo con Pyzed
Los números de velocidad importan menos que lo que se siente con un toolkit a las once de la noche cuando intentas terminar algo. Esta página recorre un proyecto Pyzed desde el primer comando hasta la app empaquetada, y compara cada paso con lo que te piden los demás toolkits. Donde decimos «medimos» o «nos encontramos», ocurrió al preparar los benchmarks.
1. Instalar
Sección titulada «1. Instalar»uv add pyzed-uipip install pyzed-uipython3 -m pip install pyzed-uipy -m pip install pyzed-uiUn solo wheel con el núcleo en Rust ya compilado, para Windows, macOS y Linux, y sin dependencias en tiempo de ejecución. Compara con lo que nos encontramos en un contenedor Ubuntu 24.04 limpio:
| Toolkit | Qué necesitó pip install allí |
|---|---|
| Pyzed | Nada más (un Linux de escritorio ya tiene la biblioteca libxkbcommon-x11 que carga; nuestro contenedor mínimo no) |
| tkinter | No se instala con pip: viene con Python, o con un paquete del sistema python3-tk en Debian y Ubuntu |
| PySide6 | Nada más, pero una descarga grande (mira el tamaño instalado) |
| Kivy, Dear PyGui | Nada más |
| Flet | flet[desktop]; el cliente de escritorio se descarga la primera vez que se ejecuta una app, y en Linux necesitó los paquetes del sistema libsecret y libgles2 |
| Toga | Falló hasta instalar libgirepository-2.0-dev y libcairo2-dev con apt, porque PyGObject se compiló desde el código fuente |
| wxPython | Sin wheels para Linux en PyPI: pip compila wxWidgets desde el código fuente (hay wheels para algunas distribuciones en wxpython.org) |
2. Primera ventana
Sección titulada «2. Primera ventana»uvx --from pyzed-ui pyzed new hola --scriptcd holauv run --with pyzed-ui main.pypyzed new hola --scriptcd holapython main.pypython3 -m pyzed new hola --scriptcd holapython3 main.pypy -m pyzed new hola --scriptcd holapy main.pyo un proyecto uv completo con linter, tipos y git con pyzed new hola. La app
es una clase con un view():
import pyzed as pzfrom pyzed import ui
class Hola(pz.App): title = "Hola" nombre = ""
def view(self): return pz.center(pz.column([ ui.input(self.nombre, lambda texto: setattr(self, "nombre", texto), placeholder="Tu nombre"), ui.heading(f"¡Hola, {self.nombre or 'mundo'}!"), ], spacing=12, max_width=320))
pz.run(Hola)Ya tiene tema oscuro, anillos de foco, estados al pasar el ratón y texto bien renderizado; nada que estilizar.
¿Cuánto código?
Sección titulada «¿Cuánto código?»Escribimos las mismas dos apps en cada toolkit, con el estilo de la documentación de cada proyecto (código), y contamos las líneas que no son vacías, comentarios ni docstrings.
- CustomTkinter6.0.014 líneas
- tkinterTk 9.0.315 líneas
- Flet1.0.417 líneas
- Pyzed1.2.019 líneas
- Dear PyGui2.3.119 líneas
- Toga0.5.719 líneas
- PySide6 (Qt)6.12.028 líneas
- Kivy2.3.131 líneas
- Flet1.0.422 líneas
- Dear PyGui2.3.129 líneas
- Pyzed1.2.031 líneas
- CustomTkinter6.0.032 líneas
- Toga0.5.735 líneas
- tkinterTk 9.0.339 líneas
- PySide6 (Qt)6.12.062 líneas
- Kivy2.3.181 líneas
El número de líneas depende del estilo, así que tómalo como guía aproximada. La diferencia mayor es qué
hacen esas líneas: en tkinter, Qt, Flet y Dear PyGui parte del código copia datos a los widgets y los
mantiene sincronizados; en Pyzed, view() es el único lugar que convierte datos en widgets.
3. Recarga en caliente
Sección titulada «3. Recarga en caliente»uv run pyzed dev main.pypyzed dev main.pypython3 -m pyzed dev main.pypy -m pyzed dev main.pyEdita view(), un módulo auxiliar o un estilo y guarda: la ventana se actualiza en el sitio, con tus datos
todavía ahí (el objeto de la app se conserva y recibe la clase nueva). Los métodos nuevos y los atributos nuevos
de __init__ aparecen sin reiniciar, y un valor inicial cambiado se aplica si la app no lo modificó (ver
Recarga en caliente). Si el código nuevo falla, el error aparece en la ventana, y
el siguiente guardado que lo corrige devuelve la app.


Flet reinicia la app al guardar y NiceGUI recarga su servidor, así que el estado en memoria empieza de cero. Qt ofrece una vista previa en vivo para QML en sus herramientas, no para código Widgets en Python. tkinter, Kivy, Dear PyGui y Toga necesitan reiniciar (o una herramienta de terceros).
4. Un diseñador visual que escribe Python
Sección titulada «4. Un diseñador visual que escribe Python»pyzed design abre Pyzed Design: arrastra componentes a un formulario, ajusta sus
propiedades, conecta eventos a manejadores en Python, edita código con autocompletado y diagnósticos (ty y
ruff) y ejecuta el formulario.

Qt tiene los diseñadores más potentes (Qt Designer, Qt Creator, Qt Design Studio). tkinter y wxPython tienen diseñadores de terceros; Kivy, Dear PyGui, Flet, Toga y NiceGUI no tienen.
5. Autocompletado y comprobación de tipos
Sección titulada «5. Autocompletado y comprobación de tipos»El paquete tiene tipos (py.typed, con stubs del núcleo en Rust), así que los editores completan los
argumentos de los widgets y los comprobadores de tipos detectan errores antes de ejecutar nada:
ui.button("Guardar", self.guardar, variant="solid", size="sm", keys="ctrl-s")# ^ el autocompletado lista cada opción, con su documentaciónLos proyectos nuevos ejecutan ty y ruff con
pyzed check.
6. Mensajes de error que dicen qué arreglar
Sección titulada «6. Mensajes de error que dicen qué arreglar»Los errores se detectan al crear el widget, con el valor que estaba mal:
ValueError: unknown button variant 'soild'ValueError: unknown icon 'plsu'; see pyzed.icons.names()ValueError: invalid color: "#12345"TypeError: text() got an unexpected keyword argument 'colr'Una excepción dentro de view() o de un callback aparece en la ventana (con recarga en caliente) o como un
traceback normal de Python que apunta a tu línea, no al código C++ o Rust de debajo.
7. Capturas y tests sin pantalla
Sección titulada «7. Capturas y tests sin pantalla»app = Todo()app.tasks = [["Escribir la documentación", False], ["Publicar", True]]app.screenshot("tareas.png", size=(420, 320))screenshot renderiza fuera de pantalla con la CPU, así que funciona en CI y en tests; mira
Tests y capturas. Otros toolkits necesitan una pantalla virtual (Xvfb) o un
capturador de pantalla para lo mismo.
8. Empaquetado
Sección titulada «8. Empaquetado»uv run pyzed build # dist/MiApp (una carpeta) o --onefilepyzed build # dist/MiApp (una carpeta) o --onefilepython3 -m pyzed build # dist/MiApp (una carpeta) o --onefilepy -m pyzed build # dist/MiApp (una carpeta) o --onefilepyzed build envuelve PyInstaller y añade lo que los formularios cargan en tiempo de ejecución. En otros:
Qt tiene pyside6-deploy (Nuitka), flet build de Flet necesita el SDK de Flutter, Toga usa Briefcase (muy
bueno, y además apunta a móviles), Kivy usa Buildozer para Android y PyInstaller para escritorio. Mira
Compilar y distribuir.
9. Trabajar con asistentes de IA
Sección titulada «9. Trabajar con asistentes de IA»Los modelos de lenguaje escriben mejor código para APIs que pueden consultar. Pyzed les da:
- un servidor MCP con la firma exacta de cada widget, la documentación, comprobaciones de código y capturas del resultado, para que un agente en Claude Code, Cursor, VS Code o Zed vea lo que ha construido;
- esta documentación como texto plano en
llms.txt; - el panel de agente del diseñador, que edita formularios contigo;
pyzed.agentspara poner modelos con herramientas dentro de tu propia app.
Flet también publica un servidor MCP; Qt ofrece Qt AI Assistant en Qt Creator (comercial, orientado a C++ y QML).