Startup optimization library for Python applications.
Zenith reduces your application's import time by combining two mechanisms: lazy import proxies (modules are not executed until first attribute access) and speculative background pre-loading (a thread pool pre-loads known modules while your app boots). A persistent cache learns which modules your app uses across runs, making every subsequent boot faster.
Compared to Python 3.15 lazy imports: Python 3.15 will defer imports until first use. Zenith goes a step further — it actively pre-loads those modules in the background based on your run history, so they are ready before you even access them.
Benchmarks run on isolated subprocesses, 5 runs averaged, loading multiprocessing, urllib.request, sqlite3, json, xml.etree.ElementTree:
| Metric | Native Python | Zenith (warm) | Saved |
|---|---|---|---|
| Avg Boot (ms) | ~52ms | ~37ms | ~15ms |
| Improvement | — | — | ~28% |
First run builds the cache. Subsequent runs benefit from speculative pre-loading. Results vary by hardware and module set.
[Application Entrypoint]
│
( zenith.ignite() )
│
┌───────────────┴──────────────────┐
▼ ▼
[sys.meta_path Hook] [ThreadPoolExecutor]
ZenithLazyFinder workers=4 (default)
Returns proxy module Pre-loads cached modules
on first import with GIL bypass per thread
│ │
▼ ▼
[First attribute access] [Module ready in sys.modules]
_zenith_load_module() called Main thread gets real module
Loads real module on demand instantly on access
ZenithLazyFinder is inserted at index 0 of sys.meta_path. Every new import statement returns a lightweight ZenithLazyModule proxy instead of executing the module immediately. The real module is only loaded the first time one of its attributes is accessed.
A ThreadPoolExecutor (4 workers by default) pre-loads modules from the persistent cache in background threads. A thread-local bypass flag prevents background threads from creating further lazy proxies, ensuring they load real modules.
On exit, Zenith writes .zenith_cache.json with the list of modules used during the session. On next launch, those modules are queued for background pre-loading before user code runs.
python3 -m venv alenia_env
source alenia_env/bin/activate
pip install alenia-zenithFor system-wide use (Docker, CI/CD):
pip install alenia-zenith --break-system-packagesimport zenith
zenith.ignite()
# Your imports — served lazily and pre-loaded in background
import pandas as pd
import numpy as np
import requestsimport zenith
zenith.ignite(file=__file__) # Scans this file for imports and pre-loads themzenith.ignite(
file=__file__, # Scan this file's imports and pre-load them
workers=8, # Background thread pool size (default: 4)
verbose=True, # Print pre-load events to stdout
exclude=["mymodule"], # Never lazy-load these packages
cache_path=".cache/zenith.json", # Custom cache location
show_banner=False, # Suppress the ASCII banner
)# Explicitly pre-load specific modules
zenith.warm("pandas", "numpy", "torch")
# Exclude packages from lazy loading
zenith.exclude("my_c_extension", "greenlet")
# Inspect current state
info = zenith.status()
# {
# "version": "1.2.0",
# "initialized": True,
# "workers": 4,
# "preloaded_count": 12,
# "cached_modules": [...],
# ...
# }
# Statically analyze a file's imports
modules = zenith.analyze("myapp/main.py")
# Clear the module cache
zenith.invalidate_cache()After installation, the zenith command is available:
# Analyze imports in a file
zenith analyze myapp/main.py --verbose
# Show cache status
zenith status
# Run a benchmark comparison
zenith benchmark --runs 5
zenith benchmark --runs 5 --modules pandas numpy requests
# Clear the cache
zenith invalidate[Zenith Analyzer] myapp/main.py
Total imports : 18
Stdlib : 6
Third-party : 12
Third-party:
- fastapi
- pydantic
- sqlalchemy
...
python3 examples/zenith_telemetry.py=========================================
ZENITH PERFORMANCE TELEMETRY
=========================================
Modules : multiprocessing, urllib.request, sqlite3, json, xml.etree.ElementTree
Runs : 5
Running...
-----------------------------------------
METRIC | NATIVE | ZENITH
-----------------------------------------
Avg Boot (s) | 0.05210s | 0.03725s
Avg Boot (ms) | 52.10ms | 37.25ms
-----------------------------------------
Saved 14.86ms (28.5% faster)
=========================================
NOTE: On first run Zenith builds its cache. Run again for warm results.
# cli.py — command line tool
import zenith
zenith.ignite(file=__file__, show_banner=False)
import click # Loaded lazily
import rich # Loaded lazily
import requests # Loaded lazily
import yaml # Loaded lazilyWhy it works: CLI tools are launched thousands of times a day. Every 30ms saved is noticeable to the user. click, rich, and requests are heavy modules that take time to initialize.
Real-world examples: pip, git, black, ruff, poetry are tools where startup time is critical.
# main.py — FastAPI, Flask, Django
import zenith
zenith.ignite(file=__file__, workers=8, show_banner=False)
import fastapi
import pydantic
import sqlalchemy
import uvicornWhy it works: In serverless environments (AWS Lambda, Google Cloud Run), the "cold start" is the biggest latency issue. Zenith allows the server to start serving requests while still loading secondary modules in the background.
# pipeline.py
import zenith
zenith.ignite(show_banner=False)
zenith.warm("pandas", "numpy", "sklearn", "matplotlib")
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifierWhy it works: pandas, numpy, and torch have some of the longest import times in the Python ecosystem (up to 500ms+ combined). With a warm cache, these are pre-loaded in the background while configuration code is running.
# devtool.py
import zenith
zenith.ignite(file=__file__)
import ast, pathlib, json
from typing import ...
import mypy, black, isortWhy it works: Dev tools are invoked constantly (on every file save, in CI/CD). The cumulative startup overhead is significant.
# app.py
import zenith
zenith.ignite(workers=4, show_banner=False)
import tkinter as tk
import PIL
import sqlite3Why it works: Python GUIs are notoriously slow to start. Zenith can pre-load secondary modules while the main window is initializing.
# manage.py or wsgi.py
import zenith
zenith.ignite(show_banner=False, exclude=["django"])
# Do not apply lazy loading to Django itself — use warm() for secondary modules
zenith.warm("PIL", "boto3", "celery")Limitation: Django has its own app importation system. Apply Zenith only to external dependencies, not the framework itself.
# First cell of the notebook
import zenith
zenith.ignite(show_banner=False)
zenith.warm("pandas", "matplotlib", "seaborn", "plotly")Limitation: In notebooks, the session lasts a long time, so the benefit of the warm cache is less noticeable. It's mainly useful for the initial kernel startup.
| Case | Reason |
|---|---|
| Short scripts (<1s total) | The overhead of ignite() outweighs the benefit |
Critical C extensions (greenlet, gevent) |
Not thread-safe for background loading. Use exclude() |
Modules using sys.modules[__name__] at import-time |
May have unexpected behavior with proxies. Add to exclude() |
| Python < 3.10 | Not supported due to type hints used |
- GIL: Zenith uses standard threading. On CPython (default), background threads share the GIL with the main thread. This means pre-loading is concurrent, not fully parallel. The benefit comes from overlapping I/O-bound disk reads with your main thread's execution.
- Cold first run: The first run has no cache and shows no speedup. The second run onward benefits from speculative pre-loading.
- C extensions: Some C extension modules are not safe to import from a background thread. Use
zenith.exclude("module_name")for those.
Distributed under the ALENIA STUDIOS TOOL LICENSE Version 1.0. See LICENSE for more information.
Contact: [email protected]
See CHANGELOG.md for the full version history.
See CONTRIBUTORS.md for the list of contributors.
See CONTRIBUTING.md to learn how to contribute.