Packaging a Castella App¶
This guide covers packaging Castella applications for distribution.
Desktop Applications¶
PyInstaller¶
PyInstaller packages your app as a standalone executable:
# With uv (recommended)
uv add --dev pyinstaller
uv run pyinstaller --onefile --windowed your_app.py
# With pip
pip install pyinstaller
pyinstaller --onefile --windowed your_app.py
Options:
--onefile: Create a single executable file--windowed: Hide the console window (for GUI apps)--name: Set the output executable name
Example with custom options:
Nuitka¶
Nuitka compiles Python to native code for better performance:
# With uv (recommended)
uv add --dev nuitka
uv run nuitka --standalone --onefile your_app.py
# With pip
pip install nuitka
nuitka --standalone --onefile your_app.py
For GUI applications:
# With uv
uv run nuitka --standalone --onefile --disable-console your_app.py
# With pip
nuitka --standalone --onefile --disable-console your_app.py
Platform-Specific Notes¶
Windows¶
- Include SDL2/GLFW DLLs if using those backends
- Set
PYSDL2_DLL_PATHenvironment variable if needed - Consider code signing for distribution
SDL2 DLL handling:
macOS¶
For proper macOS app bundles:
# Using PyInstaller
pyinstaller --onefile --windowed \
--osx-bundle-identifier com.yourname.yourapp \
your_app.py
Notes:
- Sign your app for distribution
- Create a proper
.appbundle - Test on different macOS versions
Linux¶
AppImage (recommended for distribution):
- Build with PyInstaller
- Package as AppImage for portable distribution
System packages:
Ensure system libraries are available:
Web Deployment¶
For PyScript/Pyodide web applications, see Getting Started - Web Browsers.
Basic Web Deployment¶
- Create your HTML file with PyScript setup
- Include your Python source
- Deploy to any static file server
Example project structure:
Hosting Options¶
- GitHub Pages (free)
- Netlify (free tier)
- Any static file hosting
Handling Dependencies¶
Data Files¶
Include data files (images, fonts, etc.):
PyInstaller:
In your code:
import sys
import os
if getattr(sys, 'frozen', False):
# Running as compiled
base_path = sys._MEIPASS
else:
# Running as script
base_path = os.path.dirname(__file__)
asset_path = os.path.join(base_path, 'assets', 'image.png')
Hidden Imports¶
If PyInstaller misses some imports:
Best Practices¶
-
Test the packaged app on a clean system without Python installed
-
Include all backends you might use, or specify the exact one
-
Document system requirements for your users
-
Version your releases with clear changelogs
-
Consider installer tools like NSIS (Windows) or create-dmg (macOS) for professional distribution