Modern Python client for Aspen InfoPlus.21 (IP.21) with pandas DataFrame output, tag search, and automatic retry logic
Project description
Aspy21
Python Client for Aspen InfoPlus.21 (IP.21)
Note: This is an independent, unofficial client library. Not affiliated with AspenTech.
Overview
aspy21 is a modern, high-performance Python client for Aspen InfoPlus.21 (IP.21) built on the AspenOne ProcessData REST API. It provides unified access to process historian data with pandas DataFrame output, automatic batching, and intelligent retry logic.
Key Capabilities
- REST-based communication with Aspen IP.21 historian
- Basic HTTP authentication (cross-platform compatible)
- Tag search with wildcards and description filtering
- Unified interface for analog, discrete, and text tags
- Support for RAW, INT, SNAPSHOT, and AVG reader types
- Pandas DataFrame output with optional status columns
- Configurable row limits and query parameters
- Built-in retry logic with exponential backoff
- Type-annotated and fully tested
Use Cases
- Industrial data analysis and reporting
- Integration with data analytics pipelines
- Process monitoring and dashboard development
- Time-series data extraction and transformation
Installation
Install via pip:
pip install aspy21
Requirements
- Python 3.9+
- httpx >= 0.27
- pandas >= 2.0
- tenacity >= 9.0
Quick Start
Basic Usage with Context Manager
from aspy21 import AspenClient, ReaderType
# Initialize client using context manager (recommended)
with AspenClient(
base_url="https://aspen.myplant.local/ProcessData",
auth=("user", "password")
) as client:
# Read historical data
df = client.read(
tags=["ATI111", "AP101.PV"],
start="2025-06-20 08:00:00",
end="2025-06-20 09:00:00",
interval=600,
read_type=ReaderType.RAW,
as_df=True,
)
print(df)
# Connection automatically closed
Authentication
HTTP Basic Authentication
with AspenClient(
base_url="https://aspen.example.com/ProcessData",
auth=("user", "password")
) as client:
# Your code here
pass
No Authentication
For public or internal endpoints:
with AspenClient(
base_url="http://aspen.example.com/ProcessData"
) as client:
# Your code here
pass
API Reference
AspenClient
Constructor Parameters (all except base_url are keyword-only):
| Parameter | Type | Default | Description |
|---|---|---|---|
base_url |
str | required | Base URL of Aspen ProcessData REST API |
auth |
Auth|tuple|None | None | Authentication as (username, password) tuple or httpx Auth object |
timeout |
float | 30.0 | Request timeout in seconds |
verify_ssl |
bool | True | Whether to verify SSL certificates |
datasource |
str|None | None | Aspen datasource name (required for search) |
read() Method
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
tags |
Iterable[str] | required | List of tag names to retrieve |
start |
str|None | None | Start timestamp (ISO format). When omitted, falls back to a SNAPSHOT read. |
end |
str|None | None | End timestamp (ISO format). When omitted, falls back to a SNAPSHOT read. |
interval |
int|None | None | Interval in seconds for aggregated data |
read_type |
ReaderType | INT | Data retrieval mode (auto-coerced to SNAPSHOT if no range provided) |
include_status |
bool | False | Include a <tag>_status column (historical status or snapshot quality) |
max_rows |
int | 100000 | Maximum rows to return per tag |
with_description |
bool | False | Request tag descriptions (ip_description) alongside values |
as_df |
bool | False | Return results as a pandas DataFrame instead of JSON list |
Returns:
- If
as_df=True: pandas.DataFrame with time index and columns for each tag. - If
as_df=False: List of dictionaries includingtimestamp,tag,value, and optionaldescription/status.
Snapshot reads:
- Supplying no
start/end(or explicitly choosingReaderType.SNAPSHOT) issues a snapshot SQL query that returns the latest value plusip_description.- When
include_status=True, the snapshot response also includes theip_input_qualitycode, exposed as a<tag>_statuscolumn (and asstatusin JSON output whenas_df=False) alongside the value. The timestamp reflects the request time.
search() Method
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
tag |
str | "*" |
Tag name pattern with wildcards (*, ?). Defaults to "*" (all tags). |
description |
str|None | None | Description filter (case-insensitive substring). When provided, uses SQL endpoint for server-side search. |
case_sensitive |
bool | False | Whether tag matching is case-sensitive (Browse endpoint only) |
max_results |
int | 10000 | Maximum number of results to return |
return_desc |
bool | True | Whether to return descriptions. If True, returns dicts. If False, returns tag names only. |
Returns:
- If
return_desc=True: List of dicts with 'name' and 'description' keys - If
return_desc=False: List of tag name strings
Requirements:
datasourcemust be configured in AspenClient
Search Modes:
- Tag-only search (no description): Uses Browse endpoint for fast tag name matching
- Description search (description provided): Uses SQL endpoint for server-side description filtering
Wildcards:
*- Matches any number of characters?- Matches exactly one character
Examples:
# Find all temperature tags with descriptions (Browse endpoint)
tags = client.search(tag="TEMP*")
# Returns: [{"name": "TEMP_101", "description": "Reactor temp"}, ...]
# Get just tag names without descriptions
tag_names = client.search(tag="TEMP*", return_desc=False)
# Returns: ["TEMP_101", "TEMP_102", ...]
# Search by description only (SQL endpoint)
reactor_tags = client.search(description="reactor")
# Combine tag pattern and description (SQL endpoint)
pressure_tags = client.search(tag="AI_1*", description="pressure")
ReaderType Enum
Available reader types:
ReaderType.RAW- Raw data points as storedReaderType.INT- Interpolated values at intervalsReaderType.SNAPSHOT- Current snapshot of tag valuesReaderType.AVG- Average values over intervals
Configuration
Connection Settings
with AspenClient(
base_url="https://aspen.example.com/ProcessData",
auth=("user", "password"),
timeout=60.0, # Request timeout (seconds)
verify_ssl=True, # SSL certificate verification
datasource="IP21" # Required for search operations
) as client:
# Your code here
pass
Retry Behavior
The client automatically retries failed requests with exponential backoff:
- Maximum attempts: 3
- Initial delay: 0.5 seconds
- Maximum delay: 8 seconds
Error Handling
from aspy21 import AspenClient
import httpx
try:
with AspenClient(
base_url="https://aspen.example.com/ProcessData",
auth=("user", "password")
) as client:
df = client.read(
tags=["ATI111"],
start="2025-06-20 08:00:00",
end="2025-06-20 09:00:00",
as_df=True,
)
except httpx.HTTPStatusError as e:
print(f"HTTP error: {e.response.status_code}")
except httpx.RequestError as e:
print(f"Connection error: {e}")
Development
Running Tests
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run with coverage
pytest --cov=src/aspy21 --cov-report=html
Type Checking
pyright
Code Formatting
ruff format
Dependencies
Core Dependencies
- httpx (>= 0.27) - HTTP client with async support
- pandas (>= 2.0) - DataFrame output and date parsing
- tenacity (>= 9.0) - Retry logic with exponential backoff
Development Dependencies
- pytest, pytest-cov - Testing framework
- respx - HTTP mocking for tests
- ruff - Code formatting and linting
- pyright - Static type checking
- pre-commit - Git hooks
License
This project is licensed under the MIT License. See LICENSE file for details.
Contributing
Contributions are welcome. Please ensure:
- All tests pass (
pytest) - Code is formatted (
ruff format) - Type checking passes (
pyright) - Coverage remains above 75%
Support
For issues, questions, or feature requests, please open an issue on GitHub.
Disclaimer
This project is an independent open-source client library and is not affiliated with, endorsed by, or sponsored by AspenTech. "Aspen InfoPlus.21", "IP.21", and "AspenTech" are trademarks or registered trademarks of Aspen Technology, Inc.
This software interacts with Aspen InfoPlus.21 systems through their documented REST API endpoints. Users must have appropriate licenses and authorization to access AspenTech systems.
Users are responsible for compliance with their AspenTech license agreements and applicable terms of service. This library merely provides a technical interface and does not grant any rights to AspenTech software or services.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aspy21-0.2.0b14.tar.gz.
File metadata
- Download URL: aspy21-0.2.0b14.tar.gz
- Upload date:
- Size: 601.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fd0109ce94a70c87f6cde49ab621c71021a1a165de1a04af8b6374296d3dc71
|
|
| MD5 |
0ec72e7bff5a9e53b5d6da2ec12010f7
|
|
| BLAKE2b-256 |
7783083e4df38dc25e1ca4c0813265df20adf662d7a24f5b9bc674226f5198e4
|
Provenance
The following attestation bundles were made for aspy21-0.2.0b14.tar.gz:
Publisher:
release.yml on bazdalaz/aspy21
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aspy21-0.2.0b14.tar.gz -
Subject digest:
6fd0109ce94a70c87f6cde49ab621c71021a1a165de1a04af8b6374296d3dc71 - Sigstore transparency entry: 672847868
- Sigstore integration time:
-
Permalink:
bazdalaz/aspy21@3781a185f21c8aa6b2b0001aadea36981e4ebe2c -
Branch / Tag:
refs/tags/v0.2.0b14 - Owner: https://github.com/bazdalaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3781a185f21c8aa6b2b0001aadea36981e4ebe2c -
Trigger Event:
push
-
Statement type:
File details
Details for the file aspy21-0.2.0b14-py3-none-any.whl.
File metadata
- Download URL: aspy21-0.2.0b14-py3-none-any.whl
- Upload date:
- Size: 25.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
795d84cb4a9b59c0db9ea9d2d2f68b24a0ca09f90467bfda269e5461f793e036
|
|
| MD5 |
d8db5d93ef503650fd3fd87b0c2f9c22
|
|
| BLAKE2b-256 |
2bace56aaea33c717a2f199df9b74d4b598529948f96d45115cdfdee0111c07c
|
Provenance
The following attestation bundles were made for aspy21-0.2.0b14-py3-none-any.whl:
Publisher:
release.yml on bazdalaz/aspy21
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aspy21-0.2.0b14-py3-none-any.whl -
Subject digest:
795d84cb4a9b59c0db9ea9d2d2f68b24a0ca09f90467bfda269e5461f793e036 - Sigstore transparency entry: 672847874
- Sigstore integration time:
-
Permalink:
bazdalaz/aspy21@3781a185f21c8aa6b2b0001aadea36981e4ebe2c -
Branch / Tag:
refs/tags/v0.2.0b14 - Owner: https://github.com/bazdalaz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3781a185f21c8aa6b2b0001aadea36981e4ebe2c -
Trigger Event:
push
-
Statement type: