Framework#
Streamlit is a Python framework for machine learning and data visualization that can build a beautiful online app with just a few lines of code. For front-end beginners, there is no need to learn various difficult front-end frameworks, and using Flask to create various APIs on the back end is quite simple. However, to make the front end look more appealing, one must learn various frameworks and understand how to beautify it, which Streamlit addresses.
However, Streamlit can only be deployed on a server and browsed via the web, which is not suitable for industrial software. A Japanese developer has created a wrapper framework to package Streamlit projects into desktop applications.
Streamlit + Wasm + Electron = Desktop app
whitphx/stlite: In-browser Streamlit 🎈🚀
Environment Installation#
[!NOTE]
It is assumed that you have already understood and installed nvm and the basic node.js environment. If not, please refer to another blog post Blog Frontend Secondary Development - Saturn Ring Base.
It is also assumed that you are familiar with creating Python virtual environments and the basic usage of pip, which is part of Python basics.
- According to the tutorial in the Japanese developer's repository, create a new folder as the project folder and create the following
package.jsonfile to start a new NPM project, editing thenamefield.
{
"name": "xxx",
"version": "0.1.0",
"main": "./build/electron/main.js",
"scripts": {
"dump": "dump-stlite-desktop-artifacts",
"serve": "cross-env NODE_ENV=production electron .",
"app:dir": "electron-builder --dir",
"app:dist": "electron-builder",
"postinstall": "electron-builder install-app-deps"
},
"build": {
"files": ["build/**/*"],
"directories": {
"buildResources": "assets"
}
},
"devDependencies": {
"@stlite/desktop": "^0.69.2",
"cross-env": "^7.0.3",
"electron": "33.3.1",
"electron-builder": "^25.1.7"
},
"stlite": {
"desktop": {
"files": ["app.py"],
"entrypoint": "app.py"
}
}
}
-
Run
npm installAt this point, you may encounter errors such as
npm error Cannot read properties of null (reading 'matches')ornpm error RequestError: unable to verify the first certificate. You need to delete the existing node_modules folder in the project folder. Set the npm proxy source and the electron proxy source, and clean the npm cache.Since there is no good command method to modify the electron proxy source (the methods found online are misleading), on Windows, you need to modify the .npmrc file in the C:\Users\your_username folder as follows.
registry=https://registry.npmmirror.com
strict-ssl=false
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
Then execute the following command to clear the cache, and running npm install should work without issues.
npm cache clean --force
-
Create
app.pyand write the code for the Streamlit application.Here, because the relevant configuration items
stlite.desktop.filesandstlite.desktop.entrypointinpackage.jsonspecify the name asapp.py, the file must be namedapp.py.The files and folders specified in
stlite.desktop.fileswill be bundled into the desktop application, andstlite.desktop.entrypointspecifies the entry point for the Streamlit application.
An example is as follows:
import altair as alt
import numpy as np
import pandas as pd
import streamlit as st
"""
# Welcome to Streamlit!
Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
forums](https://discuss.streamlit.io).
In the meantime, below is an example of what you can do with just a few lines of code:
"""
num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
indices = np.linspace(0, 1, num_points)
theta = 2 * np.pi * num_turns * indices
radius = indices
x = radius * np.cos(theta)
y = radius * np.sin(theta)
df = pd.DataFrame({
"x": x,
"y": y,
"idx": indices,
"rand": np.random.randn(num_points),
})
st.altair_chart(alt.Chart(df, height=700, width=700)
.mark_point(filled=True)
.encode(
x=alt.X("x", axis=None),
y=alt.Y("y", axis=None),
color=alt.Color("idx", legend=None, scale=alt.Scale()),
size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
))
For the required 4 packages, it is recommended to create a new virtual environment and install them using commands like python -m pip install altair.
-
Add more files or directories
You can edit the relevant configuration items
stlite.desktop.filesinpackage.jsonas follows. These directories and py files should comply with Streamlit's application rules, simply put, add all the files used in the Python project here.
{
// ...other fields...
"stlite": {
"desktop": {
// ...other fields...
"files": ["app.py", "pages/*.py", "assets"]
}
}
}
-
Specify package installations in the desktop application
You can edit the relevant configuration items
stlite.desktop.dependenciesinpackage.jsonas follows, simply put, add all the packages used in the Python project here.
{
// ...other fields...
"stlite": {
"desktop": {
// ...other fields...
"dependencies": ["altair", "numpy", "pandas", "streamlit"]
}
}
}
You can also edit stlite.desktop.requirementsTxtFiles as follows, which is the standard dependency specification file for Python, allowing you to add a series of dependencies.
{
// ...other fields...
"stlite": {
"desktop": {
// ...other fields...
"requirementsTxtFiles": ["requirements.txt"]
}
}
}
-
Enable node worker threads
I still haven't figured out what the so-called worker threads are, but it seems that without enabling worker threads, the ability to run Python code is not available, Pyodide cannot be properly enabled, and the Streamlit application will not start.
Edit
stlite.desktop.nodeJsWorkeras follows.
{
// ...other fields...
"stlite": {
"desktop": {
"nodeJsWorker": true
}
}
}
-
Use the
npm run dumpcommandThis creates the
./builddirectory, which contains a lot of miscellaneous items needed by this application framework, but these are all for the subsequent development server and cannot be published as an executable program. -
Use the
npm run servecommandThis command is just a wrapper for the
electroncommand, and you can find the real command inpackage.json. It will startelectronand begin the application./build/electron/main.js, which is specified in the"main"field ofpackage.json. This will start a de facto development server and open a preview of the desktop window. -
Use the
npm run app:distcommandThis is also a wrapper for the
electroncommand, which will combine the miscellaneous items in the./builddirectory into an installation package and place it in the./distfolder. electron-builder has more detailed instructions. -
The more suitable command is
npm run app:dir, which will generate a portable application in the./builddirectory.
Postscript#
This framework cannot create simple local applications and requires complete server-side support. In my conception, I abandoned its use because it cannot use the local loopback address for socketio communication.
According to the Japanese developer's statement Electron security best practices by whitphx · #445 · whitphx/stlite, this does not comply with Electron's best security practices.
Additionally, his wrapper actually uses the specified Python version to download the packages specified in our package.json for sandbox execution, while our industrial desktop applications need to support 32-bit systems. However, Streamlit's development plan does not support 32-bit systems and can only use the old version 0.62.0. Therefore, the entire framework has been abandoned for research.
This article is synchronized and updated to xLog by Mix Space. The original link is https://www.yono233.cn/posts/shoot/25_1_15_Streamlit_desktop