How to control a live viewer from Python¶
How-to. Target: a running show() viewer whose clock, data, and camera you
can change from the same Python process, and that can call back into
Python.
cesiumkit keeps a two-way bridge between Python and the browser. Python can update the clock and data sources, select or pick entities, capture the canvas, and receive click events without rebuilding the page.
Working in a notebook instead?
The Jupyter widget exposes the same control API without a server — see How to use the Jupyter widget.
1. Start a controllable viewer¶
Viewer.show() serves the page and blocks while the server runs. Start it
in a daemon thread when the same process needs to issue live commands:
from threading import Thread
from time import sleep
import cesiumkit
viewer = cesiumkit.Viewer(title="Runtime control")
Thread(target=viewer.show, kwargs={"open_browser": True}, daemon=True).start()
# Give the browser time to load before requesting values from it.
sleep(1)
Commands that only update browser state can be queued before the page
loads. Methods that return browser state — get_current_time(), pick(),
the screenshot methods — require the page to be loaded.
2. Drive the clock¶
viewer.set_time("2026-07-14T18:00:00Z")
viewer.set_multiplier(60) # one simulated minute per real second
viewer.animate(True)
print(viewer.get_current_time())
viewer.animate(False)
3. Update live data¶
Replace the first matching CZML or GeoJSON source with a URL or an in-memory JSON-compatible value:
viewer.update_czml(
[
{"id": "document", "version": "1.0"},
{"id": "vehicle", "position": {"cartographicDegrees": [-87.63, 41.88, 0]}},
]
)
viewer.update_geojson({"type": "FeatureCollection", "features": []})
For browser-side polling, keep the returned ID so the poller can be stopped:
stream_czml() accepts any iterable of CZML packet batches and returns the
daemon thread sending them:
4. Select and pick entities¶
viewer.select_entity("vehicle")
selected = viewer.selected_entity
viewer.deselect()
position = cesiumkit.Cartesian2(x=400, y=300)
frontmost = viewer.pick(position)
all_entities = viewer.drill_pick(position)
Picking returns local Python Entity objects when the IDs received from
Cesium match entities in this viewer.
5. Receive clicks in Python¶
Register callbacks before or after the server starts. Each callback
receives the clicked entity's public ID, or None for empty space:
For synchronous code, wait for the next click instead:
Multiple callbacks are supported; an exception in one is logged without stopping the others.
6. Capture the canvas¶
viewer.screenshot("viewer.png")
png_base64 = viewer.screenshot_base64()
image = viewer.canvas_to_image() # pip install "cesiumkit[images]"
Canvas capture follows browser CORS rules: remote imagery servers must permit cross-origin canvas use or the browser rejects the readback.
See
examples/11_runtime_control.py
for a complete runnable example.