Python bindings for otcat, the netcat for industrial I/O -- reads and writes Modbus TCP through the real Go core.
Project description
otcat (Python)
Python bindings for otcat, the netcat for industrial I/O. This package wraps the real, compiled Go binary — every Modbus read and write is still executed by the same tested, fuzzed Go core the main project's paper describes, not a Python reimplementation of the protocol.
from otcat import Client
c = Client("127.0.0.1:502")
v = c.read("holding:40001")
print(v.value, v.quality, v.ts)
for v in c.watch("holding:40001", interval="500ms", count=10):
print(v.ts, v.value)
c.write("holding:40001", 100) # confirm=True by default -- see "Write safety" below
Install
pip install otcat # core client only, zero extra dependencies
pip install otcat[pandas] # + DataFrame helpers
pip install otcat[fastapi] # + the async client's natural home
pip install otcat[dashboard] # + Streamlit
pip install otcat[all] # everything
The Go binary itself ships bundled inside platform-specific wheels; if
none is available for your platform, install it separately (go install github.com/QuitOperation/otcat/cmd/otcat@latest, or one of the
Cloudsmith packages) and either put it on
$PATH or point OTCAT_BINARY at it directly. See
docs/packaging.md for exactly how the bundled
binary is resolved.
Write safety: one deliberate difference from the CLI
The Go CLI refuses every write by default unless --confirm is passed
or an interactive operator answers a y/N prompt — the right default
for a human typing a command who might have a typo. Client.write()
defaults to confirm=True instead, because a library call is already
the result of a programmer's code deciding, deliberately, to write a
specific value; there is no keystroke left to protect against. Pass
confirm=False if you want the stricter behavior and are prepared to
catch WriteAbortedError.
Modules
| Module | What it's for |
|---|---|
otcat.Client |
Synchronous read/write/watch/dry_run — the core |
otcat.aio.AsyncClient |
Same API, asyncio-native — FastAPI, WebSockets |
otcat.pandas_ext |
Value lists ↔ DataFrame, plus a bounded RollingBuffer for live dashboards |
otcat.alerting |
Threshold rules with debounce → callbacks, for automations and paging |
otcat.audit |
Read-only OT asset discovery / device fingerprinting (never writes — see its module docstring) |
Examples
See examples/: a pandas time-series pull, a FastAPI
service with a live WebSocket, a Streamlit dashboard, a threshold
alerting script, and a read-only network audit script.
Exit codes → exceptions
| Go CLI exit code | Python exception |
|---|---|
| 1 | otcat.UsageError |
| 2 | otcat.ConnectionError |
| 3 | otcat.ProtocolError (.exception_code holds the Modbus exception, e.g. "0x02") |
| 4 | otcat.WriteAbortedError |
| 5 | otcat.IOFailureError |
| (n/a) | otcat.Timeout — a Python-side watchdog, distinct from otcat's own --timeout |
Testing
pip install -e ".[dev]"
pytest
Every test is an integration test against a freshly spawned
otcat-mockplc — see tests/conftest.py. Building otcat-mockplc
requires a Go 1.22+ toolchain on $PATH at test time (the shipped
wheel itself needs no Go toolchain to use, only this repo's test
suite needs one to build its own test fixture).
License
MIT — same as the Go core.
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 otcat-1.0.0.tar.gz.
File metadata
- Download URL: otcat-1.0.0.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
057e25ff78bfdce8dea790b0beb9ee77c5a2b3b8d8d8ad433c7951c43090ca66
|
|
| MD5 |
3a014fb740672ace7f1a04cdfff496d8
|
|
| BLAKE2b-256 |
d735574030cbd1533c93125c9c042508b672383d00278e41e774372ca74ef685
|
Provenance
The following attestation bundles were made for otcat-1.0.0.tar.gz:
Publisher:
python-release.yml on QuitOperation/otcat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
otcat-1.0.0.tar.gz -
Subject digest:
057e25ff78bfdce8dea790b0beb9ee77c5a2b3b8d8d8ad433c7951c43090ca66 - Sigstore transparency entry: 2220077704
- Sigstore integration time:
-
Permalink:
QuitOperation/otcat@22aa8b802ffdde5029011831028d8b7b63ceb025 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/QuitOperation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-release.yml@22aa8b802ffdde5029011831028d8b7b63ceb025 -
Trigger Event:
push
-
Statement type:
File details
Details for the file otcat-1.0.0-py3-none-any.whl.
File metadata
- Download URL: otcat-1.0.0-py3-none-any.whl
- Upload date:
- Size: 1.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7225611577afde7c78733c2d66458dc18aa93f40e2d37f4cfc3c6452c795a380
|
|
| MD5 |
cd7a1bd2bc188ed9c6b07f5dce9a696a
|
|
| BLAKE2b-256 |
620b639ca29a9a04bca7b9e36022d47aa6551af6f631a04910c7bc66a531d07c
|
Provenance
The following attestation bundles were made for otcat-1.0.0-py3-none-any.whl:
Publisher:
python-release.yml on QuitOperation/otcat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
otcat-1.0.0-py3-none-any.whl -
Subject digest:
7225611577afde7c78733c2d66458dc18aa93f40e2d37f4cfc3c6452c795a380 - Sigstore transparency entry: 2220078214
- Sigstore integration time:
-
Permalink:
QuitOperation/otcat@22aa8b802ffdde5029011831028d8b7b63ceb025 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/QuitOperation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-release.yml@22aa8b802ffdde5029011831028d8b7b63ceb025 -
Trigger Event:
push
-
Statement type: