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.0a3

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.0a3
File Size Uploaded Provenance
automotive-0.5.0a3.tar.gz 297.0 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for automotive 0.5.0a3
File
automotive-0.5.0a3-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
automotive-0.5.0a3-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.0a3-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl CPython 3.11 abi3 Linux glibc 2.17+ ARMv7l Details
automotive-0.5.0a3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
automotive-0.5.0a3-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.0a3.tar.gz

Download URL automotive-0.5.0a3.tar.gz
Size 297.0 kB
Tags Source
SHA-256 checksum
How to use checksums
26ed6f74c6978a285fb6567be99c59a7c0948ea73f5d8585e00c132a42aea59c
BLAKE2b-256 checksum
How to use checksums
8fdf2d370b67158faa82cba42f2953e5a7f24fb4dc780c108ac5f9ca5566cee4
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.0a3-cp311-abi3-win_amd64.whl

Download URL automotive-0.5.0a3-cp311-abi3-win_amd64.whl
Size 998.9 kB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
aa4af2ce5681777dda2d7e4f12bc78f2a64ed3fba37ad487fcc801fd73005c99
BLAKE2b-256 checksum
How to use checksums
650d1345e50d37615c474897042e07ba7f6082a9bf1b539aece62dcd82dec1bb
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.0a3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL automotive-0.5.0a3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 918.7 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
5eed7a8e1be17e469a78bff23df1fac5d8d8062cf904832d3246a8f6d55b21d2
BLAKE2b-256 checksum
How to use checksums
c8de9e946ed6271ee52344acbc7f4d0d0054a539f0a28903b9163c1eb5ef7ea4
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.0a3-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl

Download URL automotive-0.5.0a3-cp311-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Size 851.0 kB
Tags CPython 3.11 Linux glibc 2.17+ ARMv7l abi3
SHA-256 checksum
How to use checksums
1727d7933847527c5f3e3a0d414c7f81977b3f7125dc3b030de70264dd41392f
BLAKE2b-256 checksum
How to use checksums
377b339367a8ea6937f0e3463b90bfebb202f5a5fb901680496a9468c40f6372
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.0a3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL automotive-0.5.0a3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 892.5 kB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
bced160448f2e7134441cf4c5aeb40f623fc6b08de377391be35c120fd407b98
BLAKE2b-256 checksum
How to use checksums
ab1e2d9d7cdd7526e5b2e7404015b099cff8cc89b9ecea96d4c5792f8aeae9a4
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.0a3-cp311-abi3-macosx_11_0_arm64.whl

Download URL automotive-0.5.0a3-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
f0320dfb823dca45f3335a23fc91705719819a7c8964c74ff314ffd15a09166d
BLAKE2b-256 checksum
How to use checksums
03d5e5635506dfe922f73cf57868acdfc8250ad07a99a97c67a68b3bca18fbc3
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.0a3

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