Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Automotive for Python

PyPI Documentation

A library for synchronous and asynchronous CAN, ISO-TP, and UDS, powered by the automotive Rust crate. The distribution and import name are both automotive. Rust handles adapter I/O, protocol framing, validation, and timing; Python provides reusable configuration objects, typed values, context managers, and documented services.

Requires CPython 3.11+ and builds locally with maturin. This directory contains the Python package, its Rust extension, examples, and Scapy ECU regression tests.

Read the Python documentation for the user guide, examples, and generated API reference.

Installation and development

To test the alpha release from PyPI in another uv project:

uv add --prerelease allow automotive

To test the library from Git in another uv project, run this inside the Nix development shell:

uv add "automotive @ git+https://github.com/I-CAN-hack/automotive.git#subdirectory=python"

For development, run the following from the repository root. The Nix shell provides uv, the Rust toolchain, and native build dependencies:

nix develop
cd python
uv sync
uv run python examples/uds.py
uv check
uv format

uv check runs ty; uv format runs Ruff with default settings and a 120-character line length. uv sync installs the project and development tools; the lockfile records their versions. Use uv run maturin develop after changing Rust code when working directly in the installed development environment. For Rust formatting, run cargo fmt --all.

The Python extension always includes every adapter supported on its platform: SocketCAN on Linux, panda and PEAK USB adapters, and Vector and J2534 on Windows. Vendor drivers/DLLs and USB permissions remain necessary. The Rust crate retains feature flags for Rust applications.

Basic usage

Minimal setup retains the Rust defaults. Use CanAdapter() for automatic discovery, PeakAdapter() for default PEAK settings, or SocketCanAdapter("can0") to select a SocketCAN interface directly. Constructors open the device immediately:

import asyncio

from automotive.adapters import CanAdapter
from automotive.protocols.uds import DataIdentifier, UDSClient
from automotive.transports.isotp import IsoTP


async def main():
    adapter = CanAdapter()
    transport = IsoTP.from_id(adapter, 0x7A1)
    uds = UDSClient(transport)
    response = await uds.read_data_by_identifier(DataIdentifier.VIN)
    print(response)


asyncio.run(main())

Synchronous usage

The synchronous API mirrors the async module layout under automotive.sync. Use ordinary constructors, method calls, and receive iterators:

from automotive.sync.adapters import SocketCanAdapter
from automotive.sync.protocols.uds import DataIdentifier, UDSClient
from automotive.sync.transports.isotp import IsoTP

adapter = SocketCanAdapter("can0")
transport = IsoTP.from_id(adapter, 0x7A1)
uds = UDSClient(transport)
print(uds.read_data_by_identifier(DataIdentifier.VIN))

CanAdapter(), PeakAdapter(config), and the other named adapter classes live in automotive.sync.adapters. The import paths match their async counterparts:

Async module Sync module
automotive.adapters automotive.sync.adapters
automotive.adapters.j2534 automotive.sync.adapters.j2534
automotive.transports automotive.sync.transports
automotive.transports.isotp automotive.sync.transports.isotp
automotive.protocols.uds automotive.sync.protocols.uds
automotive.can automotive.sync.can
automotive.can.bitrate automotive.sync.can.bitrate
automotive.errors automotive.sync.errors

Both APIs share the same configuration classes, frames, enums, result types, and exceptions. These can be imported through either module hierarchy.

Hardware and subscriptions are released when their last owner is dropped. Both APIs expose a shared Transport base class accepted by UDSClient. IsoTP and J2534NativeIsoTP implement this interface. Future transports such as DoIP and HSFZ can use the same interface without depending on CAN or ISO-TP.

Transports, clients, and receivers retain their underlying resources, so they can outlive the adapter variable. For deterministic cleanup, use close() on synchronous resources or await aclose() on asynchronous resources. with and async with remain supported as optional cleanup patterns.

recv() subscribes immediately. Synchronous receivers support for and next(); async receivers support async for and anext(). Drop or close raw ISO-TP receivers before making UDS requests on the same transport. Native J2534 transports and reusable device handles have synchronous counterparts too.

One background event loop runs the existing async implementation and shuts down at process exit. Adapter construction opens hardware synchronously in both APIs, including inside an async function; Rust releases the GIL during device opening. Use the async API for awaitable sends and receives in asyncio applications. Suppression scopes in the synchronous API are local to the calling thread and context. Ctrl+C interrupts a blocking wait; an active Rust UDS exchange still drains before the next request, matching async cancellation.

Configuration

Reusable configs expose advanced settings without Rust-style builders:

import asyncio

from automotive.adapters import PeakAdapter, PeakConfig
from automotive.can import Identifier
from automotive.can.bitrate import BitrateSettings
from automotive.protocols.uds import DataIdentifier, UDSClient, UDSConfig
from automotive.transports.isotp import IsoTP, IsoTPConfig

adapter_config = PeakConfig(
    bitrate=BitrateSettings(
        bitrate=500_000, sample_point=0.8,
        data_bitrate=2_000_000, data_sample_point=0.8,
    ),
    tx_timeout=1.0,
)
transport_config = IsoTPConfig(
    tx_id=Identifier.extended(0x18DA10F1),
    fd=True, max_dlen=32, block_size=8,
    receive_separation_time_min=0.0003,
)
uds_config = UDSConfig(request_timeout=10.0, strict=True)


async def main():
    adapter = PeakAdapter(adapter_config)
    transport = IsoTP(adapter, transport_config)
    uds = UDSClient(transport, uds_config)
    print(await uds.read_data_by_identifier(DataIdentifier.VIN))


asyncio.run(main())

All Python durations are seconds. Omitting settings retains Rust defaults; explicit bitrate settings start without presets, so a nominal bitrate alone selects Classic CAN. Vector retains shared access and existing timing when no bitrate settings are supplied. resolved_bitrate reports the calculated timing; SocketCAN selects an existing OS-configured interface.

Payload inputs accept bytes, bytearray, and contiguous byte-oriented memoryview objects; payload results are bytes. Named codes are Python IntEnum members, raw numbers are accepted, and unknown received codes are preserved. Invalid arguments use Python's ValueError/TypeError/OverflowError; deadlines use TimeoutError; disconnects use ConnectionError. Protocol exceptions retain NRCs or full response bytes. See automotive.errors.

Receive subscriptions are created by recv() immediately: create one before sending, then use async for, anext(), and aclose(). Hardware, transports, and receivers also support async with. Drop or close raw ISO-TP receivers before using UDS on the same transport; raw CAN monitoring can run alongside UDS. UDS exchanges on a transport are serialized. A cancelled queued call does not transmit; an active cancelled exchange drains under the lock before the next call starts. Closing the parent interrupts dependent operations. Set request_timeout when an overall bound is needed, including repeated NRC 0x78. UDS retries idle transport receive timeouts on the same stream without resending the request or extending P2/P2*. IsoTPConfig.timeout need not exceed the UDS response waits; transmission and frame-reassembly timeouts still fail the request.

Use an ordinary context manager to suppress positive responses. Suppression supports nested scopes, restores its previous setting on exit, and is local to the current async task. Tasks created inside the scope inherit its context; already-running tasks are unaffected. Negative responses still raise errors.

with uds.suppress_positive_responses():
    await uds.tester_present()
await uds.tester_present()  # Requires a positive response again.

Examples and API documentation

The async Python examples and their counterparts in examples/sync/ mirror every Rust example, including CAN transmission, PEAK bitrate configuration, ISO-TP, UDS, and firmware queries. The synchronous firmware query visits ECUs sequentially; the async version queries them concurrently. Read installed API documentation using uv run python -m pydoc automotive.protocols.uds, or Python's help().

Run uv run python examples/can_sender.py to send one Classic CAN frame. Use uv run python examples/sync/can_sender.py for the synchronous version.

Run uv run python examples/configure_bitrate.py to configure a PEAK PCAN-USB FD adapter, or use examples/sync/configure_bitrate.py for the synchronous version.

End-to-end regression tests

On Linux, create vcan0 from the repository root:

scripts/set_up_vcan.sh

The setup script requires sudo. Then run:

cd python
uv run pytest --run-vcan -q

The regression suite starts the existing Scapy ECU scripts, verifies readiness, and closes/reaps them after each scenario. It exercises all 14 implemented UDS service IDs through both APIs, transfer round trips, suppression and pending responses, strict validation, cancellation, and ISO-TP Classic/FD framing and flow control. Tests run serially on vcan0; do not run the Rust and Python virtual-CAN suites concurrently. Without --run-vcan, the hardware-dependent tests are skipped; explicit runs fail if prerequisites are unavailable.

Metadata

Release files for automotive 0.5.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for automotive 0.5.0a2
File Size Uploaded Provenance
automotive-0.5.0a2.tar.gz 293.9 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for automotive 0.5.0a2
File
automotive-0.5.0a2-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
automotive-0.5.0a2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
automotive-0.5.0a2-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl CPython 3.11 abi3 Linux glibc 2.17+ ARMv7l Details
automotive-0.5.0a2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
automotive-0.5.0a2-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details

Total release size: 5.6 MB

Release files / automotive-0.5.0a2.tar.gz

Download URL automotive-0.5.0a2.tar.gz
Size 293.9 kB
Tags Source
SHA-256 checksum
How to use checksums
633bef9a7d181efc4ac6cf2740b7522398a2e85804f77093ec4d67f85f3b51c9
BLAKE2b-256 checksum
How to use checksums
64040a40c51855ad34fc4d8b0528025ed0c1b2885a8f1af765dab262cfb87aa3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a2-cp311-abi3-win_amd64.whl

Download URL automotive-0.5.0a2-cp311-abi3-win_amd64.whl
Size 992.3 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
cda0e76aa4bb3ce7f22ac68826d07d90f1a99ad7256fde27af89fea9e71a2a79
BLAKE2b-256 checksum
How to use checksums
42ff9fd3d099467d39c1ca715532b8e8160f1d06c548e34bd43646fbff42f261
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL automotive-0.5.0a2-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 914.9 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
5f7f746f8e7fde46eac8131bcee81c6d5ab0509c5e628133c16404f27265ba3a
BLAKE2b-256 checksum
How to use checksums
3f09ef63909b699ad1676d408a101acc9f170c8799dde05bb9190fb2ad8bb4ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a2-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl

Download URL automotive-0.5.0a2-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Size 844.5 kB
Tags CPython 3.11 Linux glibc 2.17+ ARMv7l abi3
SHA-256 checksum
How to use checksums
e2490acd4e92ebf62323eb6b344cb9f15937d6bcca42a5f0605a366f80dae404
BLAKE2b-256 checksum
How to use checksums
50ec67284415e5c1b2b3e827913213a4d0224b657948f0d67d65adcf1e6a2f75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL automotive-0.5.0a2-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 891.1 kB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
f9ac38c8b22594afcbcef572d2fa2683ea436d5e671251fff3eaf084f0f0479b
BLAKE2b-256 checksum
How to use checksums
d04f96b6fe7c53a2b848be6091d7da40cf3525aa9a418dc40cc22a3b9c180fad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / automotive-0.5.0a2-cp311-abi3-macosx_11_0_arm64.whl

Download URL automotive-0.5.0a2-cp311-abi3-macosx_11_0_arm64.whl
Size 1.6 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
345251d211628b4688a7497ba69bc65d25aaed5d4548c3af70c611fa52ed2075
BLAKE2b-256 checksum
How to use checksums
651fc9fe3da54c77f3b7d6c1fd52e345a18be49bbcbb142272649d3095ba1501
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"NixOS","version":"26.11","id":"zokor","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for automotive 0.5.0a2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page