banner
yono

yono

哈喽~欢迎光临
follow
github

Getting Started with Streamlit Desktop Projects

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 accessed via a web browser, which is not suitable for industrial software. A Japanese developer has created a wrapped framework to facilitate packaging Streamlit projects as desktop applications.

Streamlit + Wasm + Electron = Desktop app

whitphx/stlite: In-browser Streamlit 🎈🚀

Environment Installation#

[!NOTE]

It is assumed that you already understand and have 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 understand how to create Python virtual environments and the basic usage of pip, which is part of Python basics.

  1. Following the tutorial in the Japanese developer's repository, create a new folder as the project folder and create the following package.json file to start a new NPM project, editing the name field.
{
  "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"
    }
  }
}
  1. Run npm install

    At this point, you may encounter errors such as npm error Cannot read properties of null (reading 'matches') or npm 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 electron proxy source, and clean the npm cache.

    Since there is no good command method to modify the electron proxy source (the online command methods 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
  1. Create app.py and write the code for the Streamlit application.

    Here, because the relevant configuration items stlite.desktop.files and stlite.desktop.entrypoint in package.json specify app.py, the file name must be app.py.

    The files and folders specified in stlite.desktop.files will be bundled into the desktop application, and stlite.desktop.entrypoint specifies the entry 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 four packages, it is recommended to create a new virtual environment and use commands like python -m pip install altair to install them within the virtual environment.

  1. Add more files or directories

    You can edit the relevant configuration item stlite.desktop.files in package.json as follows; these directories and py files should comply with Streamlit's application rules. In simple terms, add all the files used in the Python project here.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      // ...other fields...
      "files": ["app.py", "pages/*.py", "assets"]
    }
  }
}
  1. Specify package installations in the desktop application

    You can edit the relevant configuration item stlite.desktop.dependencies in package.json as follows; simply add all the packages used in the Python project.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      // ...other fields...
      "dependencies": ["altair", "numpy", "pandas", "streamlit"]
    }
  }
}

You can also edit stlite.desktop.requirementsTxtFiles as follows; this is the standard dependency specification file for Python, where you can add a series of dependencies.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      // ...other fields...
      "requirementsTxtFiles": ["requirements.txt"]
    }
  }
}
  1. Enable node worker threads

    I still haven't figured out what 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.nodeJsWorker as follows.

{
  // ...other fields...
  "stlite": {
    "desktop": {
      "nodeJsWorker": true
    }
  }
}
  1. Use the npm run dump command

    This creates the ./build directory, which contains a lot of miscellaneous items needed for this application framework, but these are all for the development server and cannot be published as an executable program.

  2. Use the npm run serve command

    This command is just a wrapper for the electron command, which you can find out in package.json. It will start electron and begin the application ./build/electron/main.js, which is specified in the "main" field of package.json. This will start a de facto development server and open a preview of the desktop window.

  3. Use the npm run app:dist command

    This is also a wrapped electron command that will combine the miscellaneous items in the ./build directory into an installation package, placed in the ./dist folder. electron-builder has more detailed documentation.

  4. The more suitable command is npm run app:dir, which will generate a portable application in the ./build directory.

Postscript#

This framework cannot create simple local applications and requires a complete server back-end support. In my conception, I abandoned the use of local loopback addresses 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. Moreover, 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 by Mix Space to xLog. The original link is https://www.yono233.cn/posts/shoot/25_1_15_Streamlit_desktop

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.