Skip to main content

Professional build automation for EmbedDesire Python applications

Project description

EmbedDesire - Professional Python Asset Embedding

embdes is a production-ready tool for embedding static resources (images, sounds, text files, folders) directly into Python applications and building standalone executables with PyInstaller.

Features

  • Embed resources into Python applications with optional compression
  • Automatic extraction with built-in caching (100% cache hit rate)
  • Development/Runtime modes — swap between reading from disk and reading from embedded data with one call
  • PyInstaller integration — automated build process via embdes CLI
  • Persistent storage — save/load embedded data manually if needed
  • Production-ready — comprehensive logging, validation, error handling
  • Cross-platform — Windows, macOS, Linux support
  • Global CLI — callable from any directory as embdes command

Installation

pip install embdes

How It Works

embed() always returns the original file path. What changes between modes is what happens under the hood:

Mode set_runtime_mode(...) embed() behavior
Runtime mode True Skips embedding — just returns the path so you read from disk as normal
Embedded mode False Reads and stores the file in memory — the returned path is used to access embedded data in the built exe

This means your app code stays identical in both modes — you always just open(embed(...)).


Basic Usage

from embeddesire import embed, set_runtime_mode

set_runtime_mode(True)  # Read from disk (development)

embedded = embed(".\\hello.txt", id="hello", compress=True)

with open(embedded, "r") as f:
    print(f.read())

Switch to set_runtime_mode(False) when you want to work with embedded data (e.g. inside a built exe where the original files no longer exist on disk).


Building a Standalone Exe

Using embdes (Recommended)

embdes automates everything. Write your app normally, then build with one command.

app.py

from embeddesire import embed, set_runtime_mode

set_runtime_mode(True)  # During dev, reads from disk

config  = embed("config.json",    id="config",  compress=False)
sprites = embed("assets/sprites/",id="sprites", compress=True)
sounds  = embed("assets/sounds/", id="sounds",  compress=True)

with open(config, "r") as f:
    print(f.read())

# Use sprites and sounds paths however your app needs them

Build

embdes app.py

embdes will:

  1. Validate all paths passed to embed() exist on disk
  2. Execute your script to collect all embed() calls
  3. Save the embedded data to embedded_data.pkl
  4. Call PyInstaller with the pickle bundled in automatically
  5. Clean up temporary files

The resulting exe in dist/ has all your assets baked in — no external files needed.


Manual Build (Full Control)

Use this if you have an existing PyInstaller setup, a .spec file, or prefer not to use embdes.

Step 1 — Generate the pickle

Run a small preparation script once before building:

# prepare.py
from embeddesire import embed, save_embedded, set_runtime_mode

set_runtime_mode(False)  # Must be False so embed() actually stores the data

embed("config.json",    id="config",  compress=False)
embed("assets/sprites/",id="sprites", compress=True)
embed("assets/sounds/", id="sounds",  compress=True)

save_embedded("embedded_data.pkl")
python prepare.py

Step 2 — Pass the pickle to PyInstaller yourself

pyinstaller app.py --onefile --add-data "embedded_data.pkl;."

Step 3 — Load it inside the exe

# app.py
import sys, os
from embeddesire import embed, set_runtime_mode, load_embedded, extract

if getattr(sys, "frozen", False):
    # Inside the exe — load the bundled pickle, then use extract() to get files out
    load_embedded(os.path.join(sys._MEIPASS, "embedded_data.pkl"))
    config_dir = extract("config")
    config_path = os.path.join(config_dir, "config.json")
    with open(config_path, "r") as f:
        print(f.read())
else:
    # Development — read from disk as normal
    set_runtime_mode(True)
    config = embed("config.json", id="config", compress=False)
    with open(config, "r") as f:
        print(f.read())

Note: extract() only works on data already in memory from load_embedded(). It does not read from disk on its own.


Embedding Options

Disable compression for pre-compressed formats

Compression (compress=True) is on by default. Turn it off for files already compressed to avoid wasted CPU and larger output:

embed("photo.jpg",   id="photo",   compress=False)
embed("music.mp3",   id="music",   compress=False)
embed("archive.zip", id="archive", compress=False)

Extract to a specific location (manual builds)

path = extract("sprites", output_path="./runtime/sprites")

Managing Embedded Resources

from embeddesire import get_embedded_resources, remove_embedded_resource, get_cache_stats, clear_cache

# See all IDs currently embedded in memory
print(get_embedded_resources())
# ['config', 'sprites', 'sounds']

# Remove one to free memory
remove_embedded_resource("sounds")

# How many extract() calls were served from cache vs freshly written to disk
print(get_cache_stats())
# {'hits': 8, 'misses': 3, 'current_size': 0}

# Delete all temp extraction directories (next extract() call will re-extract)
clear_cache()

Error Handling

from embeddesire import embed, extract, load_embedded
from embeddesire import EmbedError, ExtractError, PersistenceError, ValidationError

try:
    embed("nonexistent/path/file.txt", id="data")
except EmbedError as e:
    print(f"Embed failed: {e}")

try:
    extract("id_that_was_never_embedded")
except ExtractError as e:
    print(f"Extract failed: {e}")

try:
    load_embedded("missing_or_corrupt.pkl")
except PersistenceError as e:
    print(f"Load failed: {e}")

Logging

from embeddesire import configure_logging, LogLevel

configure_logging(LogLevel.DEBUG)    # Full trace — sizes, cache hits, paths
configure_logging(LogLevel.WARNING)  # Quiet — only problems reported
configure_logging(LogLevel.INFO, format_string="%(levelname)s | %(message)s")

CLI Reference

embdes <script.py> [pyinstaller_args...]

Arguments after the script are passed directly to PyInstaller:

embdes app.py                           # Basic build
embdes app.py --windowed                # No console window
embdes app.py --windowed --icon=app.ico # With custom icon
embdes app.py --name=MyApp              # Custom exe name
embdes app.py --add-data "extra.db;."   # Bundle extra files too

API Reference

Function Description
embed(path, id, compress=True) Embed a file or folder; always returns the original path
extract(id, output_path=None) Extract an in-memory resource to disk (cached)
set_runtime_mode(value) True = read from disk, False = read from embedded data
save_embedded(file_path) Save all embedded data to a pickle file
load_embedded(file_path) Load embedded data from a pickle file into memory
clear_cache() Delete all temp extraction directories
get_cache_stats() Return {hits, misses, current_size} dict
get_embedded_resources() List all currently embedded IDs
remove_embedded_resource(id) Remove a resource from memory
configure_logging(level, format_string) Set log level and format

Configuration

export EMBEDDESIRE_COMPRESSION_LEVEL=9      # zlib level 0-9 (default 6)
export EMBEDDESIRE_MAX_FILE_SIZE=50000000   # bytes (default 100 MB)
export EMBEDDESIRE_MAX_CACHE_SIZE=250000000 # bytes (default 500 MB)

Requirements

  • Python 3.7+
  • PyInstaller (required only for embdes CLI builds)

License

MIT License — See LICENSE file

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

embdes-1.0.2.tar.gz (9.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

embdes-1.0.2-py3-none-any.whl (9.9 kB view details)

Uploaded Python 3

File details

Details for the file embdes-1.0.2.tar.gz.

File metadata

  • Download URL: embdes-1.0.2.tar.gz
  • Upload date:
  • Size: 9.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for embdes-1.0.2.tar.gz
Algorithm Hash digest
SHA256 3c3fcbe3e828cad6f10eb16583d0d10306a1b200016b82d3c2cddede49784f89
MD5 9d6573db727c8641a572ea5e45f1eda7
BLAKE2b-256 f4604cec7f9cebbd5f75aee4a648fe14d9968992f14ded98da2cde678c7d1311

See more details on using hashes here.

File details

Details for the file embdes-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: embdes-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 9.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for embdes-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 480de7fc59111de98830f461467f0eee548497ff866eeb9f36f6bc961dcddc89
MD5 ded9a7653e7238b21b1e862923fdab56
BLAKE2b-256 a80c2b9c8c0e7f09111bb35d0d06937580b4d217eaafd0bd4cd48e434e71f32a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page