Thin Python wrapper for the rust-ethernet-ip native library
Project description
Python Wrapper
This package is the current thin Python wrapper for the rust-ethernet-ip native library.
Current scope:
- thin bindings over the existing Rust FFI boundary
- Pythonic client lifecycle
- optional route-path connection support for routed ControlLogix targets
- generic read/write and batch operations
It is intentionally light and keeps Rust as the protocol and performance core.
If you are integrating this into a project, also read:
Local Development
Build the native library first from the repo root. The Python wrapper requires the FFI exports, so include the ffi feature:
cargo build --features ffi
Run the lightweight Python tests from the repo root:
PYTHONPATH=python python3 -m unittest discover -s python/tests
Run the optional simulator-backed integration tests by setting SIM_PLC_ADDRESS to a reachable deterministic simulator instance:
SIM_PLC_ADDRESS=127.0.0.1:44818 PYTHONPATH=python python3 -m unittest discover -s python/tests
Or ask the Python tests to launch the in-repo simulator example automatically:
RUST_ETHERNET_IP_START_SIM=1 PYTHONPATH=python python3 -m unittest discover -s python/tests
The auto-launch path prefers a prebuilt simulator binary at target/debug/examples/python_test_simulator (or .exe on Windows), then falls back to building it. To prebuild both the native FFI library and simulator:
cargo build --features ffi --example python_test_simulator
You can also launch the simulator example directly and point tests or examples at it:
cargo run --features ffi --quiet --example python_test_simulator
Load the package directly from the repo during development:
PYTHONPATH=python python3
If the native library is not in a default repo build output location, set:
export RUST_ETHERNET_IP_NATIVE_LIB=/absolute/path/to/librust_ethernet_ip.dylib
On Windows, point that variable to rust_ethernet_ip.dll.
Current MVP Surface
Client(address, route_path=None, auto_connect=True)connect()disconnect()read_tag(name)write_tag(name, value, value_type=None)read_tags(names)write_tags(items)check_health()get_diagnostics_snapshot(detailed=False)
Python float values default to PLC REAL in the wrapper.
If you need LREAL, pass it explicitly with value_type="LREAL".
Diagnostics snapshots are exposed as thin Python dataclasses with nested metrics sections.
For routed ControlLogix access, pass route_path=RoutePath(slots=[cpu_slot]).
On validated ControlLogix hardware, write_tags(...) currently executes writes sequentially in the Python wrapper so per-tag success and error reporting stays accurate on live PLCs.
Examples
python/examples/read_single_tag.pypython/examples/read_batch_tags.pypython/examples/log_tags_to_csv.pypython/examples/log_tags_to_sqlite.pypython/examples/pandas_dataframe_example.pypython/examples/fastapi_service_example.pypython/examples/collector_service.pypython/examples/mqtt_publisher_example.py
Optional example dependencies:
- analytics examples:
pip install '.[analytics]' - API examples:
pip install '.[api]' - MQTT example:
pip install '.[mqtt]'
Collector service example:
PYTHONPATH=python python3 python/examples/collector_service.py \
--config python/examples/collector_config.example.json \
--once
The collector uses batch reads and writes timestamped rows to either CSV or SQLite based on the config file.
Set RUST_ETHERNET_IP_PLC_ADDRESS to override the PLC address from the config file.
Set RUST_ETHERNET_IP_PLC_SLOT to inject a simple slot-only route path for routed ControlLogix targets.
MQTT publisher example:
PYTHONPATH=python python3 python/examples/mqtt_publisher_example.py \
--config python/examples/mqtt_publisher_config.example.json \
--once
The MQTT example publishes normalized batch snapshots to a broker topic shaped like
factory/{site}/plc/{plc_name}/snapshot.
Set RUST_ETHERNET_IP_MQTT_HOST to override the broker host from the config file.
Set RUST_ETHERNET_IP_PLC_SLOT to inject a simple slot-only route path for routed ControlLogix targets.
The FastAPI example also supports:
RUST_ETHERNET_IP_PLC_ADDRESSRUST_ETHERNET_IP_PLC_SLOTRUST_ETHERNET_IP_API_HOSTRUST_ETHERNET_IP_API_PORT
Docker example stack:
docker compose -f docker/python-stack/docker-compose.yml up --build
Scope Guardrail
This package is an enablement layer for Python users.
The Rust library remains the source of truth for:
- EtherNet/IP behavior
- correctness
- performance
- protocol semantics
Current Validation Status
- pure-Python unit tests run with the standard library
unittest - integration tests exist for simulator-backed connect/read/write/batch flows
- simulator-backed tests are skipped automatically when
SIM_PLC_ADDRESSis not set - integration tests can auto-launch the in-repo simulator with
RUST_ETHERNET_IP_START_SIM=1 - simulator-backed batch coverage includes mixed
DINT,REAL,BOOL, andSTRINGflows
Support and Collaboration
For bugs and integration questions:
- use GitHub Issues for reproducible defects
- use GitHub Discussions for usage and architecture questions
The project is also open to:
- priority issue handling
- priority feature sponsorship
- integration support for real deployments
- companies willing to provide specific PLC hardware for validation
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 Distributions
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 rust_ethernet_ip-1.2.0.tar.gz.
File metadata
- Download URL: rust_ethernet_ip-1.2.0.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff014cf40339f82176f5f14717b7d9dd479fb20923e50b52d27153597fc14f34
|
|
| MD5 |
a7dc8f9843e9613db8c571e5bc0f137c
|
|
| BLAKE2b-256 |
f7905976b0847a42f4ec2de1de324c6a0788650cb13ad55dfbc1c3706fcea79f
|
File details
Details for the file rust_ethernet_ip-1.2.0-py3-none-win_amd64.whl.
File metadata
- Download URL: rust_ethernet_ip-1.2.0-py3-none-win_amd64.whl
- Upload date:
- Size: 730.3 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef074371d867e528ceef7f746f779239fbed7d28db7f6e8d17a61a91c52145d8
|
|
| MD5 |
51b5791404485c2bcb054614da25e2ec
|
|
| BLAKE2b-256 |
5877086f66f08454ff3699fca00648b17a63ab822fb980dc66ea93668df23b5b
|
File details
Details for the file rust_ethernet_ip-1.2.0-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: rust_ethernet_ip-1.2.0-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 929.1 kB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07e6bec95fcdb20c1da82356c82fa62a0f7d87ffe3813b1048010023ad56b728
|
|
| MD5 |
63bb2fbcc072bb28b134af930f93b78c
|
|
| BLAKE2b-256 |
75f3448a800116c3a36a153b79873175396a69c2ca7757a6f75d27d1a39fa52a
|
File details
Details for the file rust_ethernet_ip-1.2.0-py3-none-macosx_11_0_universal2.whl.
File metadata
- Download URL: rust_ethernet_ip-1.2.0-py3-none-macosx_11_0_universal2.whl
- Upload date:
- Size: 780.5 kB
- Tags: Python 3, macOS 11.0+ universal2 (ARM64, x86-64)
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77fae20bcee759aca6fa2d83ae3755229447740bd88b36a632b3042fcdfa5054
|
|
| MD5 |
26cc66eb822875d1b187160ee80dcca0
|
|
| BLAKE2b-256 |
d03bb367ad0730c839cb68237cde9f9bd5fa8bff8d0ba67c49789b2c8917e5b3
|