Preface
Searching for "Python interface" on the Internet, the results are nothing more than Tkinter , wxWidgets , Qt , Gtk . They are either too big after packaging, have ugly interfaces, or have cumbersome code. These are GUIs, so what about web interfaces?
I've recommended streamlit before, and it's still worth recommending in simple scenarios. However, streamlit is really inflexible. Due to its core mechanism, some requirements are almost impossible to achieve. It's fine for making simple data dashboards.
Adding a border line in streamlit is very complicated, I’m speechless.
I need a flexible web framework that can be used as a web service website or packaged into an independent exe. Now I have found it, it is niecgui.
Take a look at the demonstration effect
I will post more tutorials about nicegui in the future. Important knowledge points will be published in the form of articles (for easy search). The video mainly demonstrates the actual combat process.
Today, I will use a small example to experience the features of nicegui that attract me:
- The most critical knowledge points to get started with nicegui
- Package standalone exe
We need to install these libraries
pip install nicegui pyinstaller pandas openpyxl
Don't forget to press three in a row. Your likes, collections, and attention are the motivation for my creation.
start up
Create the main.py file. Simply display a text to start.
- Line 3: All components are created using ui.xxxx
- Line 6: This sentence must be written at the end to start the service
We just need to simply execute the main.py script. By default, your browser will automatically open the page. The effect is like this:
Note a few points:
The console that executes the script is occupied at this time. Because nicegui starts a web service.
If you close this console, the service will stop.
nicegui uses fastapi as the web service framework
In addition, it automatically monitors python file changes in the current directory. Therefore we can directly modify the code (save the file) and the browser interface will automatically update.
nicegui has many built-in components that can be used. We don’t need to learn each component. We can just check the documentation when needed.
For more tips on using components, you can check out my follow-up video tutorials
Today's focus is to explain the key knowledge points of nicegui. I will use a very simple requirement. It’s more straightforward to look at the code:
The interface looks like this:
![图片](data:image/svg+xml,%3C%3Fxml version=‘1.0’ encoding=‘UTF-8’%3F%3E%3Csvg width=‘1px’ height=‘1px’ viewBox=‘0 0 1 1’ version=‘1.1’ xmlns=‘http://www.w3.org/2000/svg’ xmlns:xlink=‘http://www.w3.org/1999/xlink’%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=‘none’ stroke-width=‘1’ fill=‘none’ fill-rule=‘evenodd’ fill-opacity=‘0’%3E%3Cg transform=‘translate(-249.000000, -126.000000)’ fill=‘%23FFFFFF’%3E%3Crect x=‘249’ y=‘126’ width=‘1’ height=‘1’%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
- The requirement is to enter the execl file in the input box, click the button, and the table data will be displayed below.
layout
Comparing the code and interface, we can see the basic layout of nicegui:
- Components are created in the order of code execution and placed from top to bottom on the interface.
It is easy to think that it must provide a component that allows us to place components horizontally, such as ui.row: layout is not the core knowledge point of learning nicegui. Now, we do not need to pay attention to layout
event driven
Nicegui, like most interface frameworks on the market, uses event-driven process advancement. In our requirement, after clicking the button, the form needs to be loaded. Therefore, you need to define the click event of the button.
![图片](data:image/svg+xml,%3C%3Fxml version=‘1.0’ encoding=‘UTF-8’%3F%3E%3Csvg width=‘1px’ height=‘1px’ viewBox=‘0 0 1 1’ version=‘1.1’ xmlns=‘http://www.w3.org/2000/svg’ xmlns:xlink=‘http://www.w3.org/1999/xlink’%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=‘none’ stroke-width=‘1’ fill=‘none’ fill-rule=‘evenodd’ fill-opacity=‘0’%3E%3Cg transform=‘translate(-249.000000, -126.000000)’ fill=‘%23FFFFFF’%3E%3Crect x=‘249’ y=‘126’ width=‘1’ height=‘1’%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
- Lines 10-12: Define the function
- Line 14: Set button parameter on_click = custom function
- Click the button at this time and the custom function will be executed.
But, how do we add tables to custom functions? All event-driven frameworks require components to be placed in advance, even if there is currently no suitable data.
There are three official ways in nicegui. It is recommended that you read it patiently. I believe that the official documents do not explain it so logically.
I know the official methods seem quite cumbersome. Don’t worry, you can’t just use the official method, we can create our own update method. For example, "fool mode" like streamlit
Method 1: Put the empty form directly and refill the form data when you click the button
- Line 19: Create the table component below the row component. This time we need to use the table object in the click event, so define the variable table
- Line 11: Load data using pandas
- Lines 13-14: Rewrite the configuration of the table. nicegui uses aggrid, which is a very powerful front-end table library that can configure powerful tables. Here we just configure the header and data
- Line 15: Call the update function, then the table in the interface can be refreshed
The interface looks like this:
This method requires defining an empty table at the beginning, which seems unnatural.
Method 2: Use containers
We can first define a row container as a placeholder for the table:
- Line 19: Define row and use variables to "hold" the object
- Line 13: Clear container
- Line 14: Move the table into the container
This approach also seems unnatural, because the setting of the table (line 13-14) and the place where the table is defined (line 19) are divided into different places. The container needs to be cleared every time, which is troublesome.
Method 3: Define refresh function
In order to solve the incompatibility of the above methods, the official specially created a refresh decorator. In fact, it is essentially the encapsulation of method 2:
![图片](data:image/svg+xml,%3C%3Fxml version=‘1.0’ encoding=‘UTF-8’%3F%3E%3Csvg width=‘1px’ height=‘1px’ viewBox=‘0 0 1 1’ version=‘1.1’ xmlns=‘http://www.w3.org/2000/svg’ xmlns:xlink=‘http://www.w3.org/1999/xlink’%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=‘none’ stroke-width=‘1’ fill=‘none’ fill-rule=‘evenodd’ fill-opacity=‘0’%3E%3Cg transform=‘translate(-249.000000, -126.000000)’ fill=‘%23FFFFFF’%3E%3Crect x=‘249’ y=‘126’ width=‘1’ height=‘1’%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
- Lines 20-23: Define the function and add
ui.refreshable
the decorator - Line 25: Execute the function, which is equivalent to using the container placeholder in method 2
- Line 12: Due to the current version, refreshable cannot support parameters, we can only define global variables
- Line 15: Call the table box.refresh function, which is equivalent to method 2, clear the contents of the container, and then re-execute the table box function .
To be honest, the official design here is not very good. This approach makes the code more discrete due to the influence of global variables.
I have submitted an issue to the official, and it may be improved in future versions.
Does it feel like it’s a lot more troublesome than streamlit? That's true. However, we can use its features to create an operation similar to streamlit. I will introduce it in detail in the next section
Package standalone applications
What particularly attracts me about nicegui is that it allows us to directly package it into a single-file program that can be run on other computers that do not have Python installed.
First, we need to modify the code of main.py:
- In the ui.run function, set 2 parameters
- reload = False is required for packaging
- native = True, when the program starts, it will have an independent form just like an ordinary program. If this parameter is False, the browser will be triggered to open the page when starting.
Then create a build.py file in the same directory with the following code:
- This is somewhat different from the official documentation. Installing the official code makes it easy to package other Python environments, resulting in a very large final file.
- It is recommended that you use venv to create a virtual environment for packaging
Then create a build.py file in the same directory with the following code:
[External link pictures are being transferred...(img-8PdW7ayu-1689833136779)]
- This is somewhat different from the official documentation. Installing the official code makes it easy to package other Python environments, resulting in a very large final file.
- It is recommended that you use venv to create a virtual environment for packaging
The next step is to execute this file. After success, you will see a folder in the same directory dist
, which contains the packaged exe file.