Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quickstart

Use Python to receive notifications from data providers. Start by checking what your server offers, then listen for new notifications or replay past ones. You do not need to publish anything to listen.

Set the environment

You need Python 3.10 or newer and pyaviso installed in your Python environment. Ask your server operator for a server URL and credentials with permission to receive notifications.

Set these in your terminal, replacing the example values with yours:

export AVISO_BASE_URL=https://aviso.example.org
export AVISO_TOKEN=your-bearer-token

The scripts create the client with no arguments; it reads the address and the credential from these variables. If you have a username and password instead, unset AVISO_TOKEN and set AVISO_USERNAME and AVISO_PASSWORD. A token takes precedence when both are set. With neither set, the client looks in ~/.config/aviso/config.yaml and ~/.config/aviso/credentials.yaml, and requests go out anonymous only if those have no credential either. The first script prints what the client resolved, so you can check it picked up what you meant. See Configuration for where settings come from, and Authentication for naming a credential in code.

What is on your server

The server operator configures event types, each with a schema describing its notifications. The examples below use the same small mars schema as the CLI quickstart. Your server may have different event types or a different mars schema.

Save this as discover.py and run python discover.py in the terminal where you set the environment variables. It lists event types, then prints the schema for mars. If mars is absent, use a listed name and run again.

import json
import pyaviso

client = pyaviso.AvisoClient()
print(client.config)
print(client.schema().event_types)
print(json.dumps(client.schema_for("mars").as_dict(), indent=2, sort_keys=True))

On a server configured with only this example schema, the output starts with the resolved configuration (your paths and address will differ), then:

ResolvedConfig(
    base_url='https://aviso.example.org/'            (environment AVISO_BASE_URL),
    auth="bearer"                                    (environment AVISO_TOKEN or AVISO_USERNAME),
    timeout=None                                     (default),
    heartbeat_interval=None                          (default),
    ca_bundle=[]                                     (default),
    danger_accept_invalid_certs=False                (default),
)
['mars']
{
  "event_type": "mars",
  "schema": {
    "identifier": {
      "class": {
        "required": true,
        "type": "EnumHandler",
        "values": [
          "od",
          "rd"
        ]
      },
      "step": {
        "range": null,
        "required": false,
        "type": "IntHandler"
      }
    },
    "payload": {
      "required": false
    }
  },
  "status": "success"
}

The list names configured schemas, not available datasets or access rights. as_dict() makes the schema response printable as JSON.

Filters

Identifiers are labels you can filter on. Here, class must be od or rd (EnumHandler means a choice from a list). In this example, od means operational data. step is a whole number (IntHandler) for forecast hours; range: null adds no range limit.

required: true means a field must appear in a filter. You can leave out step to receive all steps. Publishing is different: a provider must supply every identifier field, including step. The optional payload carries extra information, such as a file location, rather than labels to filter on.

Use your server’s schema to adapt the event name and filters below. You do not need to configure a server schema to receive notifications from an existing service.

Listen for notifications

Save this as listen.py and run python listen.py in the same terminal. It selects mars notifications whose class is od, at any forecast step:

import pyaviso

client = pyaviso.AvisoClient()
for notification in client.listen("mars", filter={"class": "od"}):
    print(notification.payload)

The script waits for matching new notifications and prints each payload. Silence can simply mean none have arrived. For a notification carrying a file location, you would see:

{'location': 'file:///data/forecast.grib'}

Notifications with class=rd do not match. Press Ctrl+C to stop. This script does not save progress: restarting it waits for new notifications again.

Replay past notifications

To read retained history, replace the for loop in listen.py with this loop, keeping the imports and client initialization above it. Run python listen.py again:

for notification in client.listen(
    "mars", filter={"class": "od"}, start_from=0, mode="replay_only"
):
    print(notification.payload)

start_from=0 starts from the beginning of retained history. mode="replay_only" makes the script end when it catches up, rather than wait for new notifications. It prints matching payloads in sequence order. No output means no retained notifications match. Running it again reads the same retained history; it does not save a position.

Resume across restarts

For a listener that remembers its position, see State and resume. For more filters and replay options, see Listening.

What about async?

Use the regular client above for a simple script. If your application already uses asyncio, see Async for complete examples.

Publish a notification (optional, for providers)

You need permission to publish. With the schema above, save this as publish.py and run python publish.py to announce an operational forecast at step 12:

import pyaviso

client = pyaviso.AvisoClient()
response = client.notify(
    event_type="mars",
    identifier={"class": "od", "step": 12},
    payload={"location": "file:///data/forecast.grib"},
)
print(response.status)

It prints success when the server accepts the notification. Both class and step are supplied, even though step is optional in filters. The location is an example reference: publishing sends the notification, not the file, and does not grant access to the file.

An active matching listener receives this payload. To try it yourself, leave the live version of listen.py running and publish from another terminal with the same environment setup. A publish sent before the listener connects can be read with the replay loop. See Publishing for more options.