The runtime

A runtime for the whole app.

Choose where Python runs, how data moves, and how your app stays in control.

Put Python where the work belongs.

A quick calculation and a long-running model do not need the same execution environment. SwiftPython gives your Swift app three choices.

Execution Use it for What to know
In your app Short, trusted Python calls and direct package access Python.run executes on the Python thread with the GIL held. A native extension crash shares your app's process.
In worker processes Model inference, numerical work, image pipelines and parallel jobs Each worker has its own interpreter. Keep models on a worker and bring back the results you need.
In a Linux sandbox Tenant-specific dependencies, shell tools and work requiring a stronger isolation boundary Configure a sandbox provider and its runtime asset. VM use requires Apple Silicon and the virtualization entitlement.

Choose an execution model →

Load a model once. Keep using it.

A worker can retain a Python model, dataset or intermediate array across calls. Swift holds a handle to that object. A later call runs against the same worker-owned object; you do not have to reload it for every prediction.

Use OwnedPyHandle for automatic release, or release explicitly when a large object is no longer needed. Handles belong to the pool and worker generation that created them. A replaced worker does not silently inherit old objects.

Objects and lifetime →

Get results while Python is still working.

Consume a Python generator as an async sequence. Deliver generated tokens, search results or incremental transforms to your interface as they arrive. Progress events are separate from values. Stopping iteration sends cooperative cancellation.

For a conversation or media pipeline that sends and receives at the same time, use a full-duplex session. Input, output and application controls can advance independently on one pinned worker generation. The app chooses what an interruption means; sessions are not automatically replayed after worker replacement.

Streaming → · Full-duplex sessions →

Let Python call your Swift code.

Your app may own a scoring function, local service or user decision that Python needs during a job. Register a Swift callback and call it from Python. Synchronous, asynchronous, reentrant and streaming callback APIs support different control flows.

For nested work on the calling worker, use the reentrant callback context. Keep the callback registration alive for as long as Python needs it.

Python-to-Swift callbacks →

Move less data.

Return Swift values for small results. Keep large objects in the worker when the next operation is also Python. Use managed tensors for numeric data that needs shared access.

Particle Showcase uses a 16 MiB float32 particle array shared between NumPy and scoped Swift/Metal access. On its supported shared route, the particle payload is not copied for each render. Initial fills, fallback uploads and video readback can still copy data.

Data and shared memory → · Particle Showcase source ↗

Connect to native audio and graphics.

The optional audio adapter connects capture and playback to duplex sessions. Realtime audio callbacks stay outside Python; asynchronous pumps handle session work. The Metal adapter keeps a buffer owned through GPU completion and reports when a frame needed a copy instead.

Link the adapters your app uses. Core-only applications do not need the audio or Metal products.

Audio and Metal integration →

Build pipelines with dependencies.

Use ProcessPoolDAG when one operation needs another's result: load, preprocess, fan out independent jobs, then combine outputs. Nodes use the same pool APIs as ordinary calls. Worker affinity still matters when a node consumes a retained object.

Task graphs →

Ship Python with your app.

The commercial package includes a Python 3.13 runtime. Your users do not need to install Homebrew or a host interpreter. Bundle any additional Python packages for that runtime, embed the matched worker for ProcessPool use, and sign your app's nested code.

Requirement Commercial distribution
Operating system macOS 15 or newer
Build tools Swift 6 / Xcode command-line tools
Local workers Apple Silicon and Intel, matched universal binaries
VM sandboxes Apple Silicon, runtime asset and virtualization entitlement
Python Package-owned Python 3.13; extra packages bundled by your app
Distribution Swift Package Manager, XCFrameworks and matched helpers

Packaging guide →