13onb4v0s12hvk4gqhy13va.jpeg

Cree aplicaciones web personalizadas de forma fácil y rápida

Foto por Alexander Schimmeck en desempaquetar

Conozca NiceGUI, un marco de interfaz de usuario simple basado en Python que funciona sin problemas con su navegador web o como una aplicación de escritorio. Ya sea que esté creando pequeñas aplicaciones web, paneles o jugando con proyectos de robótica, NiceGUI lo hace fácil con su sencilla interfaz y muchas funciones.

El objetivo de esta publicación es convencerlo de que la pruebe enumerando los pros y los contras de esta biblioteca y mostrándole cómo puede crear e implementar una aplicación NiceGUI. (Esta no es una publicación patrocinada, solo me gusta la biblioteca 🙃)

Streamlit frente a NiceGUI: ¿Por qué cambiar?

Si bien Streamlit es bueno para crear aplicaciones interactivas, puede resultar complicado manejar eventos y estados, especialmente para proyectos más grandes. NiceGUI es diferente. Le permite controlar estados e interacciones directamente, sin necesidad de pasos adicionales ni soluciones complicadas.

Gestión de estado sencilla

NiceGUI facilita la gestión de estados. A diferencia de Streamlit, que puede restablecer estados inesperadamente, NiceGUI mantiene las cosas estables, ya sea el estado inicial o los cambios realizados por los usuarios. Puede utilizar devoluciones de llamada para manejar las interacciones del usuario de manera basada en eventos sin molestarse por una actualización de página completa y perder datos de estado.

Muchas características

NiceGUI tiene muchas características interesantes:

  • Botones, interruptores, controles deslizantes, entradas y más para interactuar.
  • Formas sencillas de organizar cosas en la pantalla.
  • Gráficos, tablas e incluso escenas 3D para elementos visuales.
  • Integración con librerías de visualización de datos como Matplotlib o Plotly.
  • Personaliza colores y estilos fácilmente.
  • Herramientas para ayudar con la codificación y las pruebas.
  • Los desarrolladores principales siempre están disponibles para responder preguntas y son muy receptivos a los comentarios en su espacio GitHub.
  • Construya sobre marcos populares: FastAPI, Vue3, Tailwind, Quasar.
  • Todo su sitio está hecho con la biblioteca NiceGUI: https://nicegui.io/documentation

Limitaciones

Si bien NiceGUI es excelente, vale la pena señalar que el tamaño más pequeño de su comunidad puede ser un poco limitante. También tiene una curva de aprendizaje un poco más larga en comparación con marcos más populares como Streamlit. Es preferible familiarizarse con CSS y Tailwind CSS para aprovechar al máximo las funciones de la biblioteca. Además, el conocimiento de FastAPI, Vue y Quasar puede brindarle mayor flexibilidad y ampliar lo que puede implementar.

Ahora, exploremos algunas características de NiceGUI y luego creemos e implementemos una aplicación de demostración.

Aplicación básica

Primero instale NiceGUI:

pip install nicegui[highcharts]

Comencemos con un ejemplo de la documentación principal:

# https://nicegui.io/documentation/section_data_elements
from nicegui import ui
from random import random

chart = ui.highchart({
'title': False,
'chart': {'type': 'bar'},
'xAxis': {'categories': ['A', 'B']},
'series': [
{'name': 'Alpha', 'data': [0.1, 0.2]},
{'name': 'Beta', 'data': [0.3, 0.4]},
],
}).classes('w-full h-64')

def update():
chart.options['series'][0]['data'][0] = random()
chart.update()

ui.button('Update', on_click=update)

ui.run()

Aquí, el módulo UI es lo que le permitirá crear un elemento UI.
En este ejemplo, primero creamos un elemento de gráfico alto y le asignamos las clases de viento de cola w-full y h-64. w-full hará que use toda la pantalla horizontalmente como respuesta y h-64 especifica la altura.

Imagen del autor

Cuando hacemos clic en el botón, se activa una función de devolución de llamada. Esta devolución de llamada actualizará los datos utilizados para el gráfico y luego los volverá a representar de manera fluida.

También puedes cambiar la devolución de llamada para agregar nuevas barras:

def update():
chart.options["xAxis"]["categories"].append(random.choice(string.ascii_uppercase))
for series in chart.options['series']:
series["data"].append(random.random())
chart.update()
Imagen del autor

Además, tenga en cuenta que actualizar la página no le hará perder sus datos. No puedes hacer eso con otras bibliotecas de UI de Python. La razón por la que funciona de esa manera aquí es que los datos se comparten entre todos los usuarios, pero hay muchas maneras de mantener los datos específicos del usuario, como el objeto app.storage.user o app.storage.browser (cuando se envuelven alrededor de un @ui.page decorador).

Pero, ¿qué sucede si desea actualizar la interfaz de usuario de forma periódica? fácil ! Simplemente cambie el elemento del botón a ui.timer

ui.timer(5, callback=lambda: (update(), ui.notify("Data Updated")))
Imagen del autor

Ahora, creemos una aplicación de demostración que permita a los usuarios elegir una categoría y luego generar un hecho aleatorio de Chuck Norris.

Primero, aquí está el código principal:

import requests  # Importing the requests library to make HTTP requests
from nicegui import ui # Importing UI components from the NiceGUI library
from nicegui_app.header import add_head_html # Importing a function to add HTML head content

# List of categories for Chuck Norris facts
CATEGORIES = [
"animal",
"career",
"celebrity",
"dev",
"fashion",
"food",
"money",
"movie",
"music",
"science",
"sport",
"travel",
]

# Class to handle Chuck Norris facts
class Fact:
def __init__(self):
self.fact = None # Initialize the fact attribute to None

# Method to update the fact based on a given category
def update_fact(self, category):
url = f"https://api.chucknorris.io/jokes/random?category={category}" # URL to Chuck Norris API

for i in range(10): # Try up to 10 times to fetch a valid fact
result = requests.get(url) # Make a GET request to the Chuck Norris API

if result.status_code == 200: # If the request is successful
result_json = result.json() # Parse the JSON response
if self.fact != result_json["value"]: # If the fetched fact is different from the current one
self.fact = result_json["value"] # Update the fact attribute
break # Exit the loop

# Function to generate the Chuck Norris fact UI
def chuck():
add_head_html() # Add HTML head content for the NiceGUI app

default_value = CATEGORIES[0] # Default category for Chuck Norris facts

fact = Fact() # Create an instance of the Fact class
fact.update_fact(default_value) # Update the fact using the default category

# Create a grid layout with 12 columns
with ui.grid(columns=12).classes("w-full"):
# Column for category selection
with ui.column().classes("col-span-4 sm:col-span-2 space-x-0"):
ui.label("Pick a fact category:") # Display a label for category selection
# Radio button group for selecting categories
category = ui.radio(
CATEGORIES,
value=default_value,
on_change=lambda _: fact.update_fact(category.value), # Update the fact when the category changes
).classes("w-full")
# Button to regenerate the fact for the selected category
ui.button(
"⟳ Re-Generate", on_click=lambda _: fact.update_fact(category.value)
)

# Column for displaying the Chuck Norris fact
with ui.column().classes(
"flex col-span-8 sm:col-span-10 w-full justify-center mx-auto max-w-screen-md"
):
# Label to display the Chuck Norris fact, bound to the fact attribute of the Fact instance
ui.label().bind_text_from(fact, "fact").classes(
"text-lg sm:text-3xl text-gray-800 bg-gray-100 rounded-lg shadow-lg p-6"
)

Ahora repasémoslo paso a paso:

Primero, realizamos las importaciones necesarias y definimos las posibles categorías.

Luego, definimos la clase que almacenará y actualizará nuestro hecho aleatorio:

class Fact:
def __init__(self):
self.fact = None # Initialize the fact attribute to None

# Method to update the fact based on a given category
def update_fact(self, category):
url = f"https://api.chucknorris.io/jokes/random?category={category}" # URL to Chuck Norris API

for i in range(10): # Try up to 10 times to fetch a valid fact
result = requests.get(url) # Make a GET request to the Chuck Norris API

if result.status_code == 200: # If the request is successful
result_json = result.json() # Parse the JSON response
if self.fact != result_json["value"]: # If the fetched fact is different from the current one
self.fact = result_json["value"] # Update the fact attribute
break # Exit the loop

Esta clase almacena el hecho en el atributo «hecho» y tiene un método update_fact que llama a la API de hechos de Chuck Norris. https://api.chucknorris.io

A continuación, definimos nuestra página en la función «tirar». NiceGUI adopta un enfoque modular que le permite definir su aplicación en múltiples módulos y archivos Python.

Definimos una instancia de nuestra clase de datos. fact = Fact() Esta es una instancia específica para cada usuario. A continuación, iniciamos el hecho utilizando el método update_fact.

Ahora comenzamos a definir nuestros elementos de UI.

Definimos una grilla con dos columnas:

  • Una primera columna que tiene nuestras opciones de categoría y botón de generar. Éste tiene las siguientes clases de viento de cola: col-span-4 sm:col-span-2. Significa que para pantallas muy pequeñas ocupará 4/12 de la pantalla, en caso contrario utilizará hasta 2/12. Esto hace que el diseño también funcione en teléfonos móviles.
  • Una segunda columna donde mostraremos el hecho.

Para la primera columna:

  • Un menú de radio ui.radio.
  • Un botón para generar un hecho aleatorio.

Ambos elementos, al hacer clic o cambiarse utilizará una devolución de llamada que llama fact.update_fact

Para la segunda columna:

  • Tenemos una ui.label que vincula su valor a fact.fact por lo que cada vez que esta variable cambie, actualizará la pantalla automáticamente.

La etiqueta tiene las siguientes clases de viento de cola: text-lg sm:text-3xl Esto hace que el texto sea más pequeño en pantallas pequeñas.

Esto le brinda la siguiente aplicación:

Imagen del autor

¡Limpio! ¿bien?

Despliegue

¡Implementar dicha aplicación es fácil! Usando CloudRun por ejemplo. Solo tienes que crear un Dockerfile y luego ejecutar las siguientes instrucciones de gcloud:

PROJECT_ID=$(gcloud config get-value project)
REPO="demo"
LOCATION="europe-west1"
IMAGE="nicegui_app"
SERVICE_NAME="nicegui-app"
VERSION="0.0.1"
GAR_TAG=$LOCATION-docker.pkg.dev/$PROJECT_ID/$REPO/$IMAGE:$VERSION

# Create repository
gcloud artifacts repositories create $REPO --repository-format=docker \
--location=$LOCATION --description="Docker repository" \
--project=$PROJECT_ID || true # If fails because already exist then its fine

# Build image
gcloud builds submit --tag $GAR_TAG

# Deploy Cloud run
gcloud run deploy $SERVICE_NAME --image=$GAR_TAG --max-instances=1 --min-instances=0 --port=8080 \
--allow-unauthenticated --region=europe-west1 --memory=0.5Gi --cpu=1 -q --no-cpu-throttling --session-affinity

Esto crea la imagen de la ventana acoplable usando la compilación en la nube y luego la implementa en CloudRun.

Las únicas opciones clave aquí son: “—sin limitación de CPU—afinidad de sesión” Esto permite que el mismo usuario sea enrutado al mismo contenedor cuando sea posible y mantiene activa la CPU entre solicitudes. Puedes probarlo aquí: https://nicegui-app-dfmj3maizq-ew.a.run.app/

En conclusión

NiceGUI es una excelente opción si desea crear interfaces de usuario de forma rápida y sencilla con Python. Le ayudará a crear potentes aplicaciones de Python en las que conservará el control total del estado interno y que podrá probar e implementar fácilmente. Con suerte, puede permitirle expresar su creatividad en sus proyectos de ciencia de datos sin estar limitado por las herramientas.

Lo que se muestra aquí es sólo una pequeña fracción de lo que puedes hacer con NiceGUI. Puede obtener más información siguiendo los enlaces a continuación.

Recursos: