Getting started#
Installation#
sgu-client requires Python 3.11 or later.
uv add sgu-client
# or: pip install sgu-client
To convert responses to pandas DataFrames and Series, install the recommended extra:
uv add "sgu-client[recommended]"
# or: pip install "sgu-client[recommended]"
Creating a client#
SGUClient is the single entry point. Endpoints are grouped by
domain on its attributes:
Attribute |
Data |
|---|---|
|
Measured groundwater levels from monitoring stations |
|
Modeled groundwater levels from SGU-HYPE |
|
Groundwater chemistry sampling sites and analysis results |
Use the client as a context manager. It reuses one HTTP session for all requests and
closes it when the with block ends:
from sgu_client import SGUClient
with SGUClient() as client:
station = client.levels.observed.get_station_by_name(station_id="95_2")
print(station.properties.station_name)
In a notebook or a long-running application, where one with block is impractical,
create the client once, reuse it, and call close() when you
are done.
The examples further down this page assume such a client.
Typed responses#
Every method returns a typed Pydantic model, so your
editor can autocomplete fields. Collections follow the GeoJSON structure of the
underlying OGC API: a features list where each feature has a geometry and
properties.
stations = client.levels.observed.get_stations(limit=5)
for station in stations.features:
print(station.properties.station_name, station.properties.municipality)
print(station.geometry.coordinates)
Fields have English names, and each maps to the Swedish name used by the SGU API (for
example station_id ↔ platsbeteckning). The API Reference lists the API name for every
field.
Dates and times#
Every date and time is a timezone-aware datetime in UTC, as the SGU API labels it (its
values end in Z):
Timestamps keep their time:
observation_date"2024-12-31T04:00:00Z"becomesdatetime(2024, 12, 31, 4, 0, tzinfo=UTC).Date-only fields arrive as
"1996-04-29Z"and become midnight UTC, so.date()gives the calendar day.Missing values are
None. A value that can’t be parsed, or that has no timezone, is alsoNone, and a warning is logged naming the field and the value.
SGU doesn’t document which timezone its data uses, so the client takes the Z at its
word. One case to keep in mind: logger readings in observation_date fit UTC, but they
could also be Swedish standard time (UTC+1) labelled as UTC.
to_dict() returns datetime objects. For JSON, use model_dump_json(), which writes
ISO 8601 strings.
Configuration#
Pass an SGUConfig to change timeouts, retries or logging:
from sgu_client import SGUClient, SGUConfig
config = SGUConfig(timeout=60, max_retries=5, log_level="DEBUG")
with SGUClient(config=config) as client:
...
See SGUConfig for all options and their defaults.
Handling errors#
All errors raised by the client inherit from SGUClientError:
from sgu_client import SGUAPIError, SGUClientError, SGUTimeoutError
try:
measurements = client.levels.observed.get_measurements_by_name(station_id="95_2")
except SGUTimeoutError:
... # the request took longer than `timeout`
except SGUAPIError as err:
print(err.status_code, err.response_data)
except SGUClientError:
... # any other client error
Convenience lookups such as get_station_by_name() raise
SGUNotFoundError when nothing matches and
SGUAmbiguousError when more than one feature matches. Both are
also ValueErrors, as are the errors for invalid arguments.