Skip to main content
The Cano Python SDK lets you track events and identify users from backend services using a simple, synchronous API — with optional async support for modern frameworks like FastAPI. The SDK queues events in a background thread, batches them automatically, and retries on transient failures so your application code stays clean and non-blocking.

Requirements

  • Python 3.8 or higher
  • No other runtime dependencies beyond the standard library and requests

Installation

Install the package from PyPI using pip:
The package is also available via conda:

Initialization

Create a single CanoClient instance when your application starts and reuse it across your codebase. The client spawns a background worker thread that handles batching and delivery automatically.
cano_client.py

Core Methods

client.track(event, user_id=None, anonymous_id=None, properties=None, timestamp=None)

Call track whenever a user performs an action you want to measure. Supply either a user_id (for authenticated users) or an anonymous_id (for unidentified visitors) — at least one is required.
Pass an ISO 8601 string to timestamp if you need to record an event that occurred in the past:

client.identify(user_id, traits=None, timestamp=None)

Call identify to associate a user ID with a set of traits. This enriches all future events from that user with the traits you provide.

client.page(user_id, name=None, properties=None)

Call page to record a server-side page or screen view — useful for server-rendered apps where the frontend SDK isn’t available.

client.alias(user_id, previous_id)

Call alias to merge two identities — for example, when a previously anonymous user signs up and you want to link their historical events to their new account.

client.flush()

Call flush to synchronously send all events currently queued in memory. This is a blocking call and waits until the request completes or times out.

client.shutdown()

Call shutdown to flush all remaining queued events and gracefully stop the background worker thread. Always call this before your process exits.
Always call client.shutdown() before your process exits — for example, in an atexit handler or a SIGTERM handler. Without it, any events still in the queue will be lost when the process terminates.

Django Middleware

You can automatically track every incoming HTTP request in a Django application by adding a lightweight middleware class. Place this in your project’s middleware.py file and add it to your MIDDLEWARE setting.
middleware.py
Add the middleware to your settings.py:
settings.py

Async Support

For async frameworks like FastAPI, Starlette, or async Django views, use AsyncCanoClient instead of CanoClient. The async client exposes the same interface but all methods are coroutines — await each call accordingly.

Error Handling and Retries

The SDK automatically retries failed requests on transient errors (HTTP 429 Too Many Requests and 5xx server errors) with exponential backoff. By default it retries up to 3 times before dropping the batch and logging an error. To handle errors explicitly, pass an on_error callback when initializing the client:
error-handling.py
The batch argument passed to on_error is the list of event dictionaries that failed to deliver, so you can log or re-queue them as needed.