7df9ebf22c
Sync labels / sync (push) Failing after 1m9s
Publish Container Image / Build and publish container image (push) Has been cancelled
Deploy Website / Deploy to GitHub Pages (push) Has been cancelled
Deploy Website / Build website and demo (push) Has been cancelled
Deploy viewer / Deploy viewer proxy to Cloudflare Workers (push) Has been cancelled
Deploy tiles / Deploy planetary tile proxy to Cloudflare Workers (push) Has been cancelled
Deploy collab / Deploy collaboration relay to Cloudflare Workers (push) Has been cancelled
CI / Dependency audit (push) Has been cancelled
CI / E2E smoke (Playwright) (push) Has been cancelled
CI / Validate CITATION.cff (push) Has been cancelled
CI / Build and test (push) Has been cancelled
165 lines
7.0 KiB
Markdown
165 lines
7.0 KiB
Markdown
# Python Console
|
||
|
||
The **Python Console** runs Python right inside the app, against the map you are
|
||
looking at. Open it from **Processing → Python Console**. It docks as a
|
||
resizable panel at the bottom of the window (drag its top edge to resize, and the
|
||
**✕** button to close it) — it does not block the rest of the app.
|
||
|
||
Python runs in your browser via [Pyodide](https://pyodide.org) (CPython compiled
|
||
to WebAssembly), so it works in both the web and desktop builds with nothing to
|
||
install. The console exposes a single object, **`geolibre`**, that drives the
|
||
live app — its methods mirror the [`geolibre` Python package](../python.md), so
|
||
what you learn here transfers to notebooks and back.
|
||
|
||
## First run
|
||
|
||
The Python runtime downloads the first time you open the console (a one-time
|
||
download of a few MB, shown as a progress message in the header). After that it
|
||
stays warm, and your variables persist as long as the app is open — even if you
|
||
close and reopen the panel.
|
||
|
||
Type code in the input box and press **Ctrl/Cmd + Enter** (or click **Run**) to
|
||
execute it. Output, return values, and errors appear in the scrollback above.
|
||
|
||
### Editing shortcuts
|
||
|
||
| Key | Action |
|
||
| --- | --- |
|
||
| **Ctrl/Cmd + Enter** | Run the current code |
|
||
| **Enter** | Newline (multi-line editing) |
|
||
| **↑ / ↓** | Recall previous / next command (when the caret is on the first / last line) |
|
||
| **Tab** or **Ctrl + Space** | Autocomplete the name or attribute at the caret |
|
||
|
||
Autocomplete introspects the **live** runtime, so `geolibre.` lists its real
|
||
methods, and your own variables and any imported modules complete too. When more
|
||
than one candidate matches, a list appears — use **↑/↓** to choose and
|
||
**Enter/Tab** to accept, or **Esc** to dismiss.
|
||
|
||
```python
|
||
geolibre.get_center() # [lng, lat] of the current view
|
||
geolibre.get_bounds() # [west, south, east, north]
|
||
geolibre.fly_to(-122.4, 37.8, zoom=10)
|
||
```
|
||
|
||
## Script editor
|
||
|
||
For multi-line scripts you want to keep, click **Show editor** (the panel icon in
|
||
the header) to open a script editor beside the console — like QGIS's Python
|
||
editor. Drag the divider to resize it, and click the icon again to hide it.
|
||
|
||
The editor **shares the console's interpreter**, so a variable or function you
|
||
define in a script is immediately usable in the console, and vice-versa.
|
||
|
||
- **New / Open / Save / Save As** work with `.py` files. On the desktop app, Save
|
||
writes back to the open file; in the browser it downloads (or uses the
|
||
File System Access API). An unsaved file shows a `•` next to its name.
|
||
- **Run** (or **Ctrl/Cmd+Enter**) executes the whole script — or just the
|
||
**selected** lines if you have a selection. Output and errors appear in the
|
||
console on the right.
|
||
- **Tab** indents, **Ctrl+Space** autocompletes, and **Ctrl/Cmd+S** saves.
|
||
|
||
## Driving the map
|
||
|
||
```python
|
||
# Add data (a GeoJSON dict, a geometry, or anything with __geo_interface__)
|
||
layer_id = geolibre.add_geojson(
|
||
{"type": "Point", "coordinates": [-122.4, 37.8]}, name="Pin"
|
||
)
|
||
|
||
# Style, toggle, and inspect layers
|
||
layer = geolibre.get_layer(layer_id)
|
||
layer.opacity = 0.6
|
||
layer.visible = False
|
||
layer.set_style(circleRadius=8, fillColor="#ff0000")
|
||
|
||
for layer in geolibre.layers:
|
||
print(layer.name, layer.type, layer.visible)
|
||
|
||
# Identify features at a point (like clicking the map)
|
||
hits = geolibre.identify(-122.4, 37.8)
|
||
```
|
||
|
||
## Async operations
|
||
|
||
The console supports top-level `await`. A few operations are asynchronous and
|
||
must be awaited:
|
||
|
||
```python
|
||
# Fetch a remote GeoJSON URL and add it
|
||
await geolibre.load_geojson("https://example.com/data.geojson", name="Data")
|
||
|
||
# Run a processing algorithm; result layers are added to the map
|
||
geolibre.list_algorithms() # discover ids + parameters
|
||
result = await geolibre.run_algorithm("buffer", {"layer": layer_id, "distance": 1000})
|
||
print(result["logs"], result["resultLayerIds"])
|
||
```
|
||
|
||
## Loading more packages
|
||
|
||
To keep startup fast, only the base runtime loads up front. Pull in additional
|
||
packages on demand:
|
||
|
||
```python
|
||
await geolibre.load_package("numpy")
|
||
import numpy as np
|
||
np.array([1, 2, 3]).mean()
|
||
|
||
await geolibre.load_package("geopandas") # also pulls shapely/pyproj/pandas
|
||
```
|
||
|
||
Any package in the [Pyodide distribution](https://pyodide.org/en/stable/usage/packages-in-pyodide.html)
|
||
is available this way.
|
||
|
||
## `geolibre` API reference
|
||
|
||
| Method | Description |
|
||
| --- | --- |
|
||
| `get_view()` | Live camera `{center, zoom, bearing, pitch, bbox}`. |
|
||
| `get_center()` | Live map center `[lng, lat]`. |
|
||
| `get_bounds()` | Live viewport bounds `[west, south, east, north]`. |
|
||
| `fly_to(lng, lat, zoom=, bearing=, pitch=, duration=)` | Animate the camera; only the given fields change. |
|
||
| `fit_bounds([w, s, e, n])` | Fit the camera to a bounding box. |
|
||
| `set_basemap(url)` | Set the basemap style (an http(s) or root-relative URL). |
|
||
| `identify(lng, lat, layer_id=None)` | Query rendered features at a point (like a click). |
|
||
| `add_geojson(data, name=)` | Add a layer from a GeoJSON dict / geometry / `__geo_interface__`; returns the layer id. |
|
||
| `await load_geojson(url, name=)` | Fetch a GeoJSON URL and add it; returns the layer id. |
|
||
| `layers` | List of [`Layer`](#layer) objects, in draw order. |
|
||
| `get_layer(layer_id)` | The `Layer` with that id (raises if absent). |
|
||
| `remove_layer(layer_id)` | Remove a layer by id. |
|
||
| `list_algorithms()` | Available processing algorithms (`id`, `name`, `group`, `parameters`). |
|
||
| `await run_algorithm(id, parameters=None)` | Run an algorithm; adds result layers and returns `{logs, resultLayerIds}`. |
|
||
| `to_image()` | Capture the current map as PNG **bytes**. |
|
||
| `await load_package(name)` | Load a Pyodide package on demand. |
|
||
|
||
### `Layer`
|
||
|
||
A handle returned by `geolibre.layers` / `geolibre.get_layer(...)`.
|
||
|
||
| Member | Description |
|
||
| --- | --- |
|
||
| `id`, `name`, `type` | Identity (read-only). |
|
||
| `visible` | Get/set visibility. |
|
||
| `opacity` | Get/set opacity (0–1). |
|
||
| `set_style(**style)` | Merge style overrides (e.g. `fillColor="#ff0000"`). |
|
||
| `get_features()` | The layer's features as [`Feature`](#feature) objects. |
|
||
| `zoom_to()` | Fit the camera to the layer's extent. |
|
||
| `remove()` | Remove the layer from the map. |
|
||
|
||
### `Feature`
|
||
|
||
A GeoJSON feature returned by `Layer.get_features()`. It *is* a plain `dict`
|
||
(so it serializes and feeds into `geopandas.GeoDataFrame.from_features`), with
|
||
convenience accessors `.geometry`, `.properties`, `.id`, and `__geo_interface__`.
|
||
|
||
## Notes & limitations
|
||
|
||
- **Runs on the main thread**, by design, so Python can drive the live map
|
||
synchronously. A long-running cell briefly pauses the UI — avoid tight loops
|
||
and prefer `await geolibre.run_algorithm(...)` for heavy work.
|
||
- **Sandboxed.** Pyodide cannot read your computer's filesystem or reach the
|
||
desktop app's local tools; network access follows the app's content-security
|
||
policy. `to_image()` therefore returns bytes rather than writing a file.
|
||
- **Same API as notebooks.** The [`geolibre` Python package](../python.md)
|
||
exposes the same methods from a Jupyter `Map` object, so console snippets and
|
||
notebook code are interchangeable.
|