Note: exporting to
.exe
can be challenging, we recommend hosting your app, click here to learn more.
Streamlit
is an open souce framework for converting data scripts into shareable web applications. It allows data scientists and machine learning engineers to build intuitive interfaces without having to know web development. In this tutorial we’ll learn some approaches of converting a Streamlit application to a double-click executable file for Windows / Linux / Mac platforms.
The main motivation behind this is that users should be able to bundle the Streamlit application and all of its dependencies into a single package. This bundled package can be easily shared with other users who do not have Streamlit or even Python installed in their machines.
Let’s create a simple streamlit application. Create a file streamlit_app.py
with the below code:
import streamlit as st
x = st.slider("Select a value")
st.write(x, "squared is", x * x)
This application can be run from the terminal using the below command:
streamlit run streamlit_app.py
Let’s see two frameworks for converting an application to a desktop application: Nativefier
and Stlite
. Both of these packages are based on Electron. Electron is a platform that easily enables writing cross-platform desktop applications using JavaScript, HTML, and CSS. Today, some of the most popular desktop apps are entirely written in Electron such as Atom, Visual Studio Code, Slack, etc.
Nativefier
Nativefier is a command-line tool that easily creates a desktop app for any web site with minimal configuration. Apps are wrapped by Electron in an OS executable (.app, .exe, etc.) for use on Windows, OSX and Linux. Note that converting Streamlit applications using Nativefier requires users to deploy the application to Streamlit Share.
Deploy your application in Streamlit Share and copy the URL of the deployed app as shown below:
Install nativefier
by running the below command:
npm install -g nativefier
Now convert your Streamlit application like so:
nativefier --name '<app.exe name>' '<streamlit sharing website url>' --platform <'windows' or 'mac' or 'linux'>
This will create the exe file in the current directory.
Package versions
Streamlit
1.19.0
Nativefier
50.0.1
Stlite
Stlite is a WebAssembly port of Streamlit that runs on Pyodide runtime. Pyodide is an experimental project from Mozilla to create a full Python data science stack that runs entirely in the browser. A Streamlit application can be converted to an exe using Stlite desktop. This approach does not require you to deploy the Streamlit application to Streamlit share.
First create a package.json
file to start a new NPM Project. You may edit the name
field.
{
"name": "streamlit_app_exe",
"version": "0.1.0",
"main": "./build/electron/main.js",
"scripts": {
"dump": "dump-stlite-desktop-artifacts",
"serve": 'NODE_ENV="production" electron .',
"pack": "electron-builder --dir",
"dist": "electron-builder",
"postinstall": "electron-builder install-app-deps",
},
"build": {"files": ["build/**/*"], "directories": {"buildResources": "assets"}},
"devDependencies": {
"@stlite/desktop": "^0.25.0",
"electron": "23.1.1",
"electron-builder": "^23.6.0",
},
}
Install Npm as follows:
npm install
Then create a directory to contain the application files, e.g., streamlit_app
. So the path of the main app file looks like streamlit_app
/streamlit_app.py
Run the dump
command to create the ./build
folder.
npm run dump streamlit_app
The dist
command bundles the ./build
directory created in the step above into application files (.app, .exe, .dmg etc.) in the ./dist directory.
npm run dist
Package versions
Streamlit
1.19.0
Stlite desktop
0.25.0
PyInstaller
PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules.
Let’s see how you can bundle a Streamlit application using PyInstaller.
Create a wrapper code run.py
to run the main application.
import streamlit
import streamlit.web.cli as stcli
import os, sys
def resolve_path(path):
resolved_path = os.path.abspath(os.path.join(os.getcwd(), path))
return resolved_path
if __name__ == "__main__":
sys.argv = [
"streamlit",
"run",
resolve_path("streamlit_app.py"),
"--global.developmentMode=false",
]
sys.exit(stcli.main())
Create a hooks file ./hooks/hook-streamlit.py
:
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata("streamlit")
Now call PyInstaller as below:
pyinstaller --onefile --additional-hooks-dir=./hooks run.py --clean
This will generate build
and dist
folders and a run.spec
file. Edit the run.spec
file to ensure paths are set properly as below:
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import copy_metadata
datas = [("{$YOURPYTHONENV}/site-packages/streamlit/runtime", "./streamlit/runtime")]
datas += collect_data_files("streamlit")
datas += copy_metadata("streamlit")
block_cipher = None
a = Analysis(
["run.py"],
pathex=["."],
binaries=[],
datas=datas,
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(...)
exe = EXE(...)
coll = COLLECT(...)
Once this command runs, the exe can be found in the path dist/run.exe
.
Execute the PyInstaller command one more time to incorporate the above changes:
pyinstaller run.spec --clean
Ensure the streamlit_app.py
is copied to the application path and run the run.exe
again.
Package versions
Streamlit
1.19.0
PyInstaller
5.8.0
Limitations
During my testing, I ran into several installation issues so I highly recommend you hosting your Streamlit app as a web application rather than exporting to EXE. You can host Streamlit apps for free in our platform. If you want to keep your app private, there are a few approaches: adding password protection or advanced authentication with Auth0.