Skip to content

Observ 👁

Observ is a Python port of Vue.js' computed properties and watchers. It is event loop/framework agnostic and has no dependencies, so it can be used in any project targeting Python >= 3.13.

Observ provides two benefits for stateful applications:

  1. You no longer need to manually invalidate and recompute state (e.g. by dirty flags):
    • computed state is invalidated automatically
    • computed state is lazily re-evaluated
  2. You can react to changes in state (computed or not), enabling unidirectional flow:
    • state changes lead to view changes (e.g. a state change callback updates a UI widget)
    • the view triggers input events (e.g. a mouse event is triggered in the UI)
    • input events lead to state changes (e.g. a mouse event updates the state)

A taste of observ

from observ import computed, reactive, watch

state = reactive({"count": 0, "items": []})

@computed
def total():
    return state["count"] + len(state["items"])

def on_total_changed(new, old):
    print(f"total changed from {old} to {new}")

watcher = watch(total, on_total_changed, sync=True)

state["items"].append("thing")  # prints: total changed from 0 to 1
state["count"] += 1             # prints: total changed from 1 to 2

No dirty flags, no manual notification: mutating the state through the reactive proxy is enough for observ to figure out what changed and who needs to know about it.

Where to go next

  • Follow the Quick Start to learn the core concepts in a few minutes.
  • Read the Guide for an in-depth look at reactivity, computed state, watchers and scheduling.
  • Browse the API Reference for the complete public API.
  • Curious how it all works? The Internals section explains the architecture under the hood.
  • Check out the Examples to see observ integrated with Qt and rendercanvas.
  • Collagraph: reactive user interfaces in Python, built on top of observ.
  • Reliev: the store (with undo/redo support) that used to be part of observ.