Skip to main content
RxPY provides composable asynchronous data streams. This is a practical guide focused on common patterns in this codebase.

Quick Start: Using an Observable

Given a function that returns an Observable, here’s how to use it:
session=rx

The .pipe() Pattern

Chain operators using .pipe():
session=rx

Common Operators

Transform: map

session=rx

Filter: filter

session=rx

Limit emissions: take

session=rx

Flatten nested observables: flat_map

session=rx

Rate Limiting

sample(interval) - Emit latest value every N seconds

Takes the most recent value at each interval. Good for continuous streams where you want the freshest data.
session=rx

throttle_first(interval) - Emit first, then block for N seconds

Takes the first value then ignores subsequent values for the interval. Good for user input debouncing.
session=rx

Difference Between sample and throttle_first

session=rx

What is an Observable?

An Observable is like a list, but instead of holding all values at once, it produces values over time. The key difference from iterators: with an Observable, you don’t control when values arrive. A camera produces frames at 30fps whether you’re ready or not. An iterator waits for you to call next(). Observables are lazy. An Observable is just a description of work to be done - it sits there doing nothing until you call .subscribe(). That’s when it “wakes up” and starts producing values. This means you can build complex pipelines, pass them around, and nothing happens until someone subscribes. The three things an Observable can tell you:
  1. “Here’s a value” (on_next) - A new value arrived
  2. “Something went wrong” (on_error) - An error occurred, stream stops
  3. “I’m done” (on_completed) - No more values coming
The basic pattern:
That’s it. You create or receive an Observable, then subscribe to start receiving values. When you subscribe, data flows through a pipeline: output Key property: Observables are lazy. Nothing happens until you call .subscribe(). This means you can build up complex pipelines without any work being done, then start the flow when ready. Here’s the full subscribe signature with all three callbacks:
session=rx

Disposables: Cancelling Subscriptions

When you subscribe, you get back a Disposable. This is your “cancel button”:
session=rx
Why does this matter?
  • Observables can be infinite (sensor feeds, websockets, timers)
  • Without disposing, you leak memory and keep processing values forever
  • Disposing also cleans up any resources the Observable opened (connections, file handles, etc.)
Rule of thumb: Whenever you subscribe, save the disposable because you have to unsubscribe at some point by calling disposable.dispose(). In dimos modules: Every Module has a self._disposables (a CompositeDisposable) that automatically disposes everything when the module closes:
session=rx

Creating Observables

There are two common callback patterns in APIs. Use the appropriate helper:

From register/unregister APIs

Use callback_to_observable when the API has separate register and unregister functions that take the same callback reference:
session=create

From subscribe-returns-unsub APIs

Use to_observable when the subscribe function returns an unsubscribe callable:
session=create

From scratch with rx.create

session=create

CompositeDisposable

As we know we can always dispose subscriptions when done to prevent leaks:
session=dispose
For multiple subscriptions, use CompositeDisposable:
session=dispose

Reference

See RxPY documentation for complete operator reference.