Meet NiceGUI, a easy Python-based UI framework that works easily along with your net browser or as a desktop app. Whether or not you’re making small net apps, dashboards, or taking part in with robotics tasks, NiceGUI makes it straightforward with its straightforward interface and plenty of options.
The objective of this submit is to persuade you to attempt it out by itemizing the professionals and cons of this library by displaying you how one can construct and deploy a NiceGUI app. (This isn’t a sponsored submit, I identical to the library 🙃)
Streamlit vs. NiceGUI: Why Swap?
Whereas Streamlit is sweet for making interactive apps, it may be tough to deal with occasions and states, particularly for larger tasks. NiceGUI is totally different. It allows you to management states and interactions instantly, while not having additional steps or hacky workarounds.
Easy State Administration
NiceGUI makes managing states straightforward. In contrast to Streamlit, which might reset states unexpectedly, NiceGUI retains issues regular, whether or not it’s the beginning state or modifications made by customers. You should utilize callbacks to deal with consumer interactions in event-based method with out getting irritated by a full web page refresh and dropping state knowledge.
A lot of Options
NiceGUI has many cool options:
- Buttons, switches, sliders, inputs, and extra for interplay.
- Straightforward methods to rearrange issues on the display.
- Charts, tables, and even 3D scenes for visuals.
- Integration with knowledge visualization libraries like Matplotlib or Plotly.
- Customise colours and types simply.
- Instruments to assist with coding and testing.
- Important devs are at all times out there to reply questions and are very receptive to suggestions on their GitHub area.
- Construct on high of in style frameworks: FastAPI, Vue3, Tailwind, Quasar.
- Their entire web site is made with the NiceGUI library: https://nicegui.io/documentation
Limitations
Whereas NiceGUI is nice, it’s value noting that its smaller group dimension is likely to be a bit limiting. It additionally has a barely longer studying curve in comparison with extra in style frameworks like Streamlit. It’s preferable to get accustomed to CSS and Tailwind CSS to profit from the library’s options. Additionally, information of FastAPI, Vue and Quasar can offer you higher flexibility and prolong what you may implement.
Now, lets discover some options of NiceGUI after which construct and deploy a demo app.
Primary app
First set up NiceGUI:
pip set up nicegui[highcharts]
Lets begin from an instance from the principle documentation:
# https://nicegui.io/documentation/section_data_elements
from nicegui import ui
from random import randomchart = ui.highchart({
'title': False,
'chart': {'kind': 'bar'},
'xAxis': {'classes': ['A', 'B']},
'sequence': [
{'name': 'Alpha', 'data': [0.1, 0.2]},
{'identify': 'Beta', 'knowledge': [0.3, 0.4]},
],
}).courses('w-full h-64')
def replace():
chart.choices['series'][0]['data'][0] = random()
chart.replace()
ui.button('Replace', on_click=replace)
ui.run()
Right here, the UI module is what’s going to will let you create a UI component.
On this instance, first we create a highchart component, we assign to it the tailwind courses w-full and h-64. w-full will make it use the entire display horizontally in a response method and h-64 specifies the peak.
After we click on on the button, a callback perform is triggered. This callback will replace the information used for the chart after which re-renders it in a fluid method.
You may as well change the callback so as to add new bars:
def replace():
chart.choices["xAxis"]["categories"].append(random.selection(string.ascii_uppercase))
for sequence in chart.choices['series']:
sequence["data"].append(random.random())
chart.replace()
Additionally, discover that refreshing the web page doesn’t make you lose your knowledge! You’ll be able to’t try this with another Python UI libraries. The explanation why it really works that approach right here is that knowledge is shared amongst all customers, however there are many methods to maintain knowledge user-specific just like the app.storage.consumer object or app.storage.browser (when wrapped round a @ui.web page
decorator).
However, what if you wish to replace the UI on a recurrent timer? straightforward ! Simply change the button component to ui.timer
ui.timer(5, callback=lambda: (replace(), ui.notify("Knowledge Up to date")))
Now, allow us to construct a demo app that lets customers decide a class then permits them to generate a random Chuck Norris Truth.
First, right here is the principle code:
import requests # Importing the requests library to make HTTP requests
from nicegui import ui # Importing UI parts from the NiceGUI library
from nicegui_app.header import add_head_html # Importing a perform so as to add HTML head content material# Checklist of classes for Chuck Norris info
CATEGORIES = [
"animal",
"career",
"celebrity",
"dev",
"fashion",
"food",
"money",
"movie",
"music",
"science",
"sport",
"travel",
]
# Class to deal with Chuck Norris info
class Truth:
def __init__(self):
self.reality = None # Initialize the actual fact attribute to None
# Technique to replace the actual fact based mostly on a given class
def update_fact(self, class):
url = f"https://api.chucknorris.io/jokes/random?class={class}" # URL to Chuck Norris API
for i in vary(10): # Attempt as much as 10 instances to fetch a legitimate reality
outcome = requests.get(url) # Make a GET request to the Chuck Norris API
if outcome.status_code == 200: # If the request is profitable
result_json = outcome.json() # Parse the JSON response
if self.reality != result_json["value"]: # If the fetched reality is totally different from the present one
self.reality = result_json["value"] # Replace the actual fact attribute
break # Exit the loop
# Perform to generate the Chuck Norris reality UI
def chuck():
add_head_html() # Add HTML head content material for the NiceGUI app
default_value = CATEGORIES[0] # Default class for Chuck Norris info
reality = Truth() # Create an occasion of the Truth class
reality.update_fact(default_value) # Replace the actual fact utilizing the default class
# Create a grid format with 12 columns
with ui.grid(columns=12).courses("w-full"):
# Column for class choice
with ui.column().courses("col-span-4 sm:col-span-2 space-x-0"):
ui.label("Choose a reality class:") # Show a label for class choice
# Radio button group for choosing classes
class = ui.radio(
CATEGORIES,
worth=default_value,
on_change=lambda _: reality.update_fact(class.worth), # Replace the actual fact when the class modifications
).courses("w-full")
# Button to regenerate the actual fact for the chosen class
ui.button(
"⟳ Re-Generate", on_click=lambda _: reality.update_fact(class.worth)
)
# Column for displaying the Chuck Norris reality
with ui.column().courses(
"flex col-span-8 sm:col-span-10 w-full justify-center mx-auto max-w-screen-md"
):
# Label to show the Chuck Norris reality, sure to the actual fact attribute of the Truth occasion
ui.label().bind_text_from(reality, "reality").courses(
"text-lg sm:text-3xl text-gray-800 bg-gray-100 rounded-lg shadow-lg p-6"
)
Now allow us to undergo it step-by-step:
First, we make the required imports and outline the potential classes.
Then, we outline the category that can retailer and replace our random reality:
class Truth:
def __init__(self):
self.reality = None # Initialize the actual fact attribute to None# Technique to replace the actual fact based mostly on a given class
def update_fact(self, class):
url = f"https://api.chucknorris.io/jokes/random?class={class}" # URL to Chuck Norris API
for i in vary(10): # Attempt as much as 10 instances to fetch a legitimate reality
outcome = requests.get(url) # Make a GET request to the Chuck Norris API
if outcome.status_code == 200: # If the request is profitable
result_json = outcome.json() # Parse the JSON response
if self.reality != result_json["value"]: # If the fetched reality is totally different from the present one
self.reality = result_json["value"] # Replace the actual fact attribute
break # Exit the loop
This class shops the actual fact within the attribute “reality” and has a way update_fact that calls the Chuck Norris info api. https://api.chucknorris.io
Subsequent, we outline our web page within the “chuck” perform. NiceGUI adopts a modular strategy that allows you to outline your app over a number of modules and python recordsdata.
We outline an occasion of our knowledge class reality = Truth()
It is a particular occasion to every consumer. Subsequent, we init the actual fact utilizing the update_fact technique.
Now, we begin defining our UI parts.
We outline a grid with two columns:
- A primary column that has our class choices and generate button. This one has the next tailwind courses: col-span-4 sm:col-span-2. It signifies that for very small screens it’s going to deplete 4/12 of the display, in any other case it’s going to deplete 2/12. This makes the design work in cellphones too.
- A second column the place we’ll show the actual fact.
For the primary column:
- A radio menu ui.radio.
- A button to generate a random reality.
Each parts, when clicked or modified will use a callback that calls reality.update_fact
For the second column:
- Now we have a ui.label that binds its worth to
reality.reality
so every time this variable modifications, it’s going to replace the show routinely.
The label has the next tailwind courses: text-lg sm:text-3xl This makes it so the textual content is smaller on small screens.
This provides you the next app:
Neat! proper?
Deployment
Deploying such app is straightforward! Utilizing CloudRun for instance. You simply must create a Dockerfile after which run the next gcloud directions:
PROJECT_ID=$(gcloud config get-value venture)
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 as a result of exist already then its fantastic
# Construct picture
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
This builds the docker picture utilizing cloud construct after which deploys it to CloudRun.
The one key choices listed here are: “ — no-cpu-throttling — session-affinity” This permits the identical consumer to be routed the identical container when potential and retains the CPU alive between requests. You’ll be able to attempt it out right here: https://nicegui-app-dfmj3maizq-ew.a.run.app/
In Conclusion
NiceGUI is a superb selection if you wish to make consumer interfaces shortly and simply with Python. It is going to show you how to construct highly effective python apps the place you keep full management of the inner state and that you would be able to take a look at and deploy simply. Hopefully, it will probably will let you categorical your creativity in your knowledge science tasks with out being restricted by instruments.
What was proven right here is only a small fraction of what you are able to do with NiceGUI. You’ll be able to study extra by following the hyperlinks under.
Assets: