0%

Embed Python Runtime into Tauri Application

December 26, 2025

Python

Rust

Tauri

1. Demonstration of the Bundled Result

2. Why do we Bundle the Python Runtime into The Application?

  • We can spin up a web server locally written in python and develop agentic solution to the desktop application without the need to host a webserver to provide exactly the same service. This provides much fewer latency and much higher privacy.

  • User can use their own API_KEY and AI_MODEL without us the developer to reinvent a complicated pricing plan to count how much the user has consumed. So we can concentrate on building the agentic system.

  • It also pave a way for the future LLM model that can be hosted locally (or externally via additional devices). This embedding approach will provide me a boilerplate to develop agentic software at the expense of software file size (bundling a runtime requires a lot of disk space).

3. Prepare Python Runtime in Tauri Resource Folder

3.1. Project Structure

3.2. Shell Script to Install Runtime and Preintall Required Packages

3.2.1. What Packages to Include? Steps to Install Runtime
  1. From project structure we will copy a requirements.txt from python-backend/ into src-tauri/resources/python-runtime. We will be downloading both python runtime and required packages into this python-runtime/ directory.

    This resources/ directory is the location to bundle additional resources into our Tauri appplication.

    If our uv project has included new packages, we will need to update the requirements.txt by

    uv pip compile pyproject.toml -o requirements.txt
  2. Next we check that whether we have downloaded the python runtime, if so, we will skip it.

  3. If not, we will download and unzip the python runtime via wget and tar -xzf

  4. Next according to requirements.txt we install all required dependencies into $ARCH/lib/python3.12/site-packages

  5. In 〈3.2.2. Implementation of the Shell Script〉 we will further do a clean up process (line 106-147) to remove all the symlinks and unpermitted files when doing the bundling process into a dmg file for Mac.

    This step is to solve the following problem when I first attempt to bundle the runtime:

3.2.2. Implementation of the Shell Script

We prepare an npm script

    "install-python-runtime": "sh install_python_runtime.sh"

in package.json, where install_python_runtime.sh is defined by:

1# install_python_runtime.sh
2
3#!/bin/bash
4# Download and install Python 3.12 standalone runtime if not present
5
6set -e
7
8SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9RUNTIME_DIR="$SCRIPT_DIR/src-tauri/resources/python-runtime"
10
11echo "Checking Python runtime installation..."
12
13# Check if runtime already exists
14if [ -d "$RUNTIME_DIR/aarch64" ] || [ -d "$RUNTIME_DIR/x86_64" ]; then
15    echo "✓ Python runtime already installed"
16    exit 0
17fi
18
19echo "Python runtime not found. Installing..."
20
21# Detect architecture
22ARCH=$(uname -m)
23if [ "$ARCH" = "arm64" ]; then
24    ARCH="aarch64"
25    PYTHON_URL="https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-3.12.7+20241016-aarch64-apple-darwin-install_only.tar.gz"
26elif [ "$ARCH" = "x86_64" ]; then
27    PYTHON_URL="https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-3.12.7+20241016-x86_64-apple-darwin-install_only.tar.gz"
28else
29    echo "ERROR: Unsupported architecture: $ARCH"
30    exit 1
31fi
32
33echo "Downloading Python 3.12.7 for $ARCH..."
34mkdir -p "$RUNTIME_DIR"
35cd "$RUNTIME_DIR"
36
37# Download with wget (with progress bar)
38if ! wget --show-progress -O python.tar.gz "$PYTHON_URL"; then
39    echo "ERROR: Failed to download Python runtime"
40    rm -f python.tar.gz
41    exit 1
42fi
43
44# Verify it's a valid tar.gz file
45if ! file python.tar.gz | grep -q "gzip compressed"; then
46    echo "ERROR: Downloaded file is not a valid gzip archive"
47    echo "File type: $(file python.tar.gz)"
48    rm -f python.tar.gz
49    exit 1
50fi
51
52echo "Extracting Python runtime..."
53if ! tar -xzf python.tar.gz; then
54    echo "ERROR: Failed to extract Python runtime"
55    rm -f python.tar.gz
56    exit 1
57fi
58
59# Move extracted files to arch-specific directory
60if [ -d "python" ]; then
61    mv python "$ARCH"
62    echo "✓ Python runtime installed to: $RUNTIME_DIR/$ARCH"
63else
64    echo "ERROR: Unexpected archive structure"
65    exit 1
66fi
67
68# Clean up archive
69rm python.tar.gz
70
71echo "✓ Python runtime extracted"
72echo ""
73
74# Copy requirements.txt from python-backend to python-runtime
75if [ -f "$SCRIPT_DIR/python-backend/requirements.txt" ]; then
76    echo "Copying requirements.txt from python-backend..."
77    cp "$SCRIPT_DIR/python-backend/requirements.txt" "$RUNTIME_DIR/requirements.txt"
78    echo "✓ Requirements file copied"
79else
80    echo "WARNING: python-backend/requirements.txt not found"
81fi
82
83# Install dependencies
84echo "Installing Python dependencies..."
85PYTHON_BIN="$ARCH/bin/python3.12"
86TARGET_DIR="$ARCH/lib/python3.12/site-packages"
87
88if [ -f "$RUNTIME_DIR/requirements.txt" ]; then
89    $PYTHON_BIN -m pip install \
90        --no-cache-dir \
91        --target "$TARGET_DIR" \
92        -r "$RUNTIME_DIR/requirements.txt"
93    
94    echo "✓ Dependencies installed"
95else
96    echo "WARNING: No requirements.txt found. Skipping dependency installation."
97fi
98
99echo ""
100echo "Running post-installation cleanup..."
101
102# Navigate to architecture directory
103cd "$ARCH" || exit 1
104
105# 1. Remove Python cache files
106echo "1. Removing Python cache files..."
107find . -name "*.pyc" -delete
108find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
109
110# 2. Remove macOS metadata files
111echo "2. Removing macOS metadata files..."
112find . -name ".DS_Store" -delete
113
114# 3. Clear extended attributes (quarantine flags)
115echo "3. Clearing extended attributes..."
116xattr -rc . 2>/dev/null
117
118# 4. Check for and resolve any symlinks
119echo "4. Checking for symlinks..."
120SYMLINK_COUNT=$(find . -type l | wc -l | tr -d ' ')
121if [ "$SYMLINK_COUNT" -gt 0 ]; then
122    echo "   Found $SYMLINK_COUNT symlinks. Resolving them..."
123    find . -type l | while read link; do
124        target=$(readlink "$link")
125        if [ -f "$(dirname "$link")/$target" ] || [ -f "$target" ]; then
126            rm "$link"
127            if [ -f "$(dirname "$link")/$target" ]; then
128                cp "$(dirname "$link")/$target" "$link"
129            else
130                cp "$target" "$link"
131            fi
132            echo "   Resolved: $link"
133        fi
134    done
135else
136    echo "   No symlinks found"
137fi
138
139# 5. Normalize all file permissions
140echo "5. Normalizing file permissions..."
141find . -type f -exec chmod 644 {} +
142find . -type d -exec chmod 755 {} +
143
144# 6. Re-apply execute permissions to binaries
145echo "6. Setting execute permissions on binaries..."
146chmod +x bin/python* bin/2to3* bin/idle3* bin/pydoc3* bin/pip* 2>/dev/null
147find lib/python3.12/site-packages -type f -name "*.so" -exec chmod 755 {} \; 2>/dev/null
148
149echo ""
150echo "✓ Python runtime installation and setup complete!"
151echo "✓ Runtime is ready for bundling"
152echo ""
153echo "Location: $RUNTIME_DIR/$ARCH"