Peter Žáčik
11/07/2025, 7:09 AMMarvin
11/07/2025, 7:09 AMMarvin
11/07/2025, 7:14 AMpip install prefect and your dependencies, then start a Process worker or serve your flows.
- Workers concept: Workers overview
- Windows server notes (if you’re self-hosting): Windows server guide
3) If you must produce a single EXE (unsupported but doable)
Key idea: avoid dynamic entrypoints and the full CLI; embed a small, static wrapper that starts a Process worker and let Prefect deliver flow runs from your work pool.
A. Minimal wrapper script (start a Process worker)
# run_worker.py
import os
from prefect.workers.process import ProcessWorker
def main():
pool = os.environ.get("PREFECT_WORK_POOL")
if not pool:
raise SystemExit("Set PREFECT_WORK_POOL to the name of your work pool.")
queues = os.environ.get("PREFECT_WORK_QUEUES")
work_queues = [q.strip() for q in queues.split(",")] if queues else None
worker = ProcessWorker(
work_pool_name=pool,
work_queues=work_queues,
name=os.environ.get("PREFECT_WORKER_NAME"),
)
# Optional: healthcheck endpoint for service monitoring
worker.start(with_healthcheck=True)
if __name__ == "__main__":
main()
B. Build with PyInstaller
- Pin exact versions of Python/Prefect/dependencies for repeatable builds.
- Collect Prefect and heavy deps so dynamic/lazy imports are included; include certifi data for TLS.
- Example (PowerShell, line breaks for readability):
pyinstaller --onefile --name prefect-worker `
--collect-all prefect `
--collect-all anyio `
--collect-all httpx `
--collect-all sqlalchemy `
--collect-all pydantic `
--collect-all rich `
--collect-all click `
--collect-data certifi `
--hidden-import=sniffio `
--hidden-import=cloudpickle `
run_worker.py
Notes and caveats:
- Dynamic imports: Prefect loads modules and “collections” dynamically. The --collect-all prefect flag helps, but you may still need to add more --collect-all or --hidden-import entries based on what your flows import.
- Certificates: Without certifi data, HTTPS calls to Prefect Cloud/Server can fail.
- Don’t use entrypoint-based flow loading in a frozen app (e.g., strings like "package.module:flow"). Import your flows directly if you’re bundling your flow code into the EXE, or better yet, just run a worker and keep your flow code accessible via your normal deployment mechanism.
- CLI embedding: Trying to ship the full prefect CLI inside the EXE is fragile; prefer the programmatic worker wrapper above.
- Test on a clean Windows VM that mimics the server. If the EXE crashes, rebuild with --debug to reveal missing modules.
- Running as a service: Consider using NSSM or Windows Services to keep the EXE running and auto-restart.
When to consider alternatives like zipapps/PEX/PyOxidizer/Nuitka
- Zipapps (shiv/pex) produce a single file but still require a system Python.Marvin
11/07/2025, 7:14 AM