Skip to main content

Observ 👁

Vue.js-style reactivity for Python. Wrap your state in a reactive proxy, and observ tracks every read and write for you: computed values invalidate themselves, watchers fire when something they depend on changes. No dirty flags, no manual invalidation, no dependency bookkeeping.

📖 Documentation · 📦 PyPI · 🧪 Examples (Qt, rendercanvas)

🖼️ Building a GUI?

Head straight to Collagraph — a full-featured, Vue-inspired declarative UI framework built on top of observ. If you're looking for a strong reactive GUI framework for your Python Qt/PySide applications, Collagraph is the main entrypoint; observ is the reactivity engine underneath it.

Why observ?

  • Automatic dependency tracking — computed state knows exactly what it depends on and lazily re-evaluates only when needed.
  • React to any change — watch plain state or computed state and build unidirectional data flow: state changes drive view changes, input events drive state changes.
  • Zero dependencies, framework agnostic — a pure Python library (≥ 3.9) that plugs into any event loop: asyncio, Qt, or your own.
  • Fully typed — a PEP 561 typed package, checked with ty in CI.

Quick start

pip install observ
from observ import computed, reactive, watch

state = reactive({
    "todos": [
        {"title": "groceries", "done": False},
        {"title": "dishes", "done": True},
    ],
})

@computed
def progress():
    done = sum(todo["done"] for todo in state["todos"])
    return f"{done}/{len(state['todos'])} done"

watcher = watch(progress, lambda new: print(new), sync=True)

# Mutate the plain dicts and lists you already have —
# observ sees every change, no matter how deeply nested:
state["todos"][0]["done"] = True                            # prints: 2/2 done
state["todos"].append({"title": "laundry", "done": False})  # prints: 2/3 done

# ...but you only ever react when a *result* actually changes:
state["todos"][1]["title"] = "do the dishes"                # (no print)

No subclasses to inherit, no observable fields to declare, no signals to wire up: reactive() takes your existing data, and dependencies are tracked automatically simply by using it.

Continue with the Quick Start tutorial, or dive into the Guide and API Reference.

Related projects

  • 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.
  • Patchdiff: diffing and patching for plain Python data structures — the same dicts, lists and sets you'd wrap with observ.

Metadata

Release files for observ 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for observ 1.0.0
File Size Uploaded
observ-1.0.0.tar.gz 67.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for observ 1.0.0
File Interpreter ABI Platform
observ-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 94.0 kB

Release files / observ-1.0.0.tar.gz

Download URL observ-1.0.0.tar.gz
Size 67.7 kB
Tags Source
SHA-256 checksum
How to use checksums
290bf5a45009ecc5d48e6d2b0a9b47e103e56948045be1237974298f55c170fd
BLAKE2b-256 checksum
How to use checksums
103cc37c12be0c46745f82f7994bedb9302b69a9014e4711589c1ebf6328ebdc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Release files / observ-1.0.0-py3-none-any.whl

Download URL observ-1.0.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
179b7520723420150789d965394a970c31a2f455d4700e3108315130b1110f38
BLAKE2b-256 checksum
How to use checksums
f90b55c42220c691f6458ff713603a12c6e800cc0f4770e6b8441aaad56ec541
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.18.0

2 release files

0.17.3

2 release files

0.17.2

2 release files

0.17.1

2 release files

0.17.0

2 release files

0.16.1

2 release files

0.16.0

2 release files

0.15.1

2 release files

0.14.1

2 release files

0.14.0

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.10.0

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page