H2O Wave
H2O Wave is a lightweight software stack for building beautiful, low-latency, real-time, browser-based applications and dashboards entirely in Python, without requiring HTML, Javascript, or CSS expertise. It excels at capturing data, visualizations, and graphics from multiple sources and broadcasting them live over the web. The current version is 1.8.4, with frequent releases often including security updates.
Common errors
-
httpx connection err [Errno 111] Connect call failed
cause The Python Wave app (running via Uvicorn, Gunicorn, etc.) cannot connect to the H2O Wave server (`waved`). This often happens when `waved` is not running or is not accessible at the expected address/port.fixStart the `waved` server separately. If running on different hosts or non-default ports, configure the Wave app with `H2O_WAVE_ADDRESS` environment variable to point to the correct `waved` address, e.g., `H2O_WAVE_ADDRESS='http://your-waved-host:10101'`. -
UI hangs in an infinite loading spinner after button click (in unicast mode).
cause The app handler for the button click event completed without making any changes to `q.page` or updating any UI component. In unicast mode, the browser expects a UI update to acknowledge the event and dismiss the loading state.fixEven if no visual change is intended, explicitly update a UI component or a dummy card within your handler (e.g., `q.page['feedback_card'] = ui.message_bar(type='info', text='Action complete!')` or `q.page['temp'].items = []`) before `await q.page.save()`. -
urllib.error.URLError: urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (on macOS during `wave fetch`)
cause This error on macOS indicates that Python's SSL certificate store is not correctly configured or updated, preventing it from verifying SSL certificates when downloading resources.fixNavigate to `/Applications/Python X.Y` (where X.Y is your Python version) and execute the `Install Certificates.command` script. This updates the certificate store.
Warnings
- breaking Wave 1.0 introduced minor breaking changes, particularly affecting routing. The `handle_on` mechanism was introduced to address issues with `q.args` order, which could lead to unexpected behavior in older versions.
- gotcha When deploying with an ASGI server like Uvicorn, the Wave server (`waved`) must be run separately from the Python app. `wave run` automatically starts `waved` for development, but for production, you need to manage both processes independently.
- gotcha Incorrect usage of state scopes (`q.app`, `q.user`, `q.client`) can lead to performance or UX issues. For example, loading a static dataset into `q.client` will cause it to be re-uploaded for every browser connection, wasting resources.
- gotcha In `unicast` mode (the default for applications), if a button click or other event handler does not result in *any* UI update (e.g., just printing to console), the UI may appear to hang with an infinite loading spinner.
- gotcha Disabling TLS verification using `H2O_WAVE_NO_TLS_VERIFY` environment variable or `--no-tls-verify` parameter is a significant security risk and should only be done for development purposes, never in production environments.
Install
-
pip install h2o-wave
Imports
- Q
from h2o_wave import Q
- main
from h2o_wave import main
- app
from h2o_wave import app
- ui
from h2o_wave import ui
Quickstart
from h2o_wave import Q, app, ui, main
@app('/')
async def serve(q: Q):
q.page['hello'] = ui.markdown_card(
box='1 1 2 2',
title='Hello World!',
content='This is a simple H2O Wave app.'
)
await q.page.save()
# To run this app, save it as `app.py` and execute `wave run app.py` in your terminal.
# Then, navigate to http://localhost:10101 in your browser.