Read CAN bus capture logs in different formats into one common frame stream
Project description
capkit
capkit is a Python library that reads CAN bus capture logs into one common
frame stream. Every supported format parses into the same frozen Frame
dataclass, so code that consumes frames never depends on which tool captured
the log.
Use it to:
- read captures from different tools as one lazy stream of typed
Frameobjects - probe a file for header metadata without scanning the frame body
- detect the log format from the file extension or the file content
- skip real-world log noise by default, or reject it with
strict=True - feed frames into dbckit for DBC signal decoding
| Format | Reader name | Extensions | Status | Dependency |
|---|---|---|---|---|
| Kvaser CanKing TXT | kvaser-txt |
.txt |
Supported | none |
| candump text | candump |
.log |
Supported | none |
| Vector ASC | vector-asc |
.asc |
Supported | none |
| PCAN TRC | pcan-trc |
.trc |
Planned | none |
| Generic CSV | csv-table |
.csv |
Planned | none |
| Vector BLF | vector-blf |
.blf |
Planned adapter | python-can |
| ASAM MF4 | asam-mf4 |
.mf4 |
Planned adapter | asammdf |
See format support for the exact dialect each reader accepts, and the roadmap for sequencing.
Install
pip install capkit
Requires Python >=3.11. capkit has no runtime dependencies.
Design
FrameandLogMetaare frozen, slotted dataclasses.read()is lazy and keeps constant parser state, so file size does not matter.- Timestamps are returned exactly as recorded in the source, never rebased or converted to absolute time.
- A format is added only when a real captured fixture pins its dialect under
tests/fixtures/; unsupported dialects fail clearly instead of parsing approximately.
Quick Start
import capkit
# stream frames
for frame in capkit.read("trace.txt"):
print(frame.timestamp, hex(frame.arbitration_id), frame.data.hex())
# header metadata only
meta = capkit.probe("trace.txt")
print(meta.format, meta.start_time)
# registered reader names
print(capkit.available_formats()) # ['candump', 'kvaser-txt', 'vector-asc']
The public API is six names: read, probe, available_formats,
register_reader, Frame, and LogMeta.
Features
Format detection
An explicit format= names a reader and takes precedence over the file
extension:
frames = capkit.read("capture.bin", format="kvaser-txt")
Without format=, capkit matches the extension against registered readers and
sniffs the first 4 KiB when the extension is unknown or ambiguous.
Add your own reader
Register a zero-argument reader class to make it available to read(),
probe(), and format detection:
from collections.abc import Iterator
from pathlib import Path
import capkit
class MyReader:
name: str = "my-format"
extensions: tuple[str, ...] = (".mylog",)
def __init__(self, *, strict: bool = False) -> None:
self.strict = strict
def sniff(self, sample: str) -> bool:
return sample.startswith("MYLOG")
def probe(self, path: Path) -> capkit.LogMeta:
return capkit.LogMeta(format=self.name)
def read(self, path: Path) -> Iterator[capkit.Frame]:
# Parse path lazily and yield capkit.Frame objects here.
yield from ()
capkit.register_reader(MyReader)
Registration is process-global. Installed packages can also advertise reader
classes through the capkit.readers entry-point group; capkit discovers and
caches them on the first read(), probe(), or available_formats() call.
dbckit's .txt entry point sniffs among all registered readers, so a reader
whose sniff() uniquely matches the content of a .txt log is used there
too, regardless of the extensions it claims.
Dirty logs and strict mode
Readers skip headers, trailers, comments, blank lines, and unrelated noise by
default. Pass strict=True to raise a line-numbered ValueError on the first
unrecognized nonblank line instead:
frames = capkit.read("trace.txt", strict=True)
A frame record whose DLC disagrees with its data bytes raises in both modes; corrupt frames are never silently dropped.
Use with dbckit
dbckit decodes CAN frames against a DBC database. capkit and dbckit are separate packages — neither depends on or imports the other — with adjacent jobs: capkit turns bytes on disk into frames, dbckit turns frames plus a DBC into signals.
import capkit
import dbckit
db = dbckit.load("truck.dbc")
for decoded in dbckit.decode_frames(db, capkit.read("trace.txt")):
print(decoded.timestamp, decoded.signals)
capkit also registers its readers in dbckit's dbckit.readers entry-point
group. With both packages installed, dbckit.decode_log() reads .txt,
.log, and .asc logs through capkit directly:
for decoded in dbckit.decode_log(db, "trace.txt"):
print(decoded.signals)
Scope and Caveats
- Kvaser dialects with absolute start-time headers are not supported;
probe()returnsstart_time=Noneforkvaser-txt. - candump error-flag records are skipped by default and rejected in strict mode; decoding them as CAN error frames is not claimed.
- Vector ASC relative timestamp directives and non-English month names are rejected instead of being interpreted approximately.
- capkit reads frames only: no DBC or signal awareness (that is dbckit's job), no hardware I/O, no log writing, no dataframe export, no CLI.
Documentation
- Format support — supported formats and the exact dialect each reader accepts
- API reference — the public API contract
- Recipes — counting IDs, filtering, time windows, CSV export, and dataframes in a few lines of standard library
Development
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
The dev extra includes dbckit so the entry-point integration tests run; the
core and contract suites pass without it.
License
MIT
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 capkit-0.2.0.tar.gz.
File metadata
- Download URL: capkit-0.2.0.tar.gz
- Upload date:
- Size: 42.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35e0337249f3d14493d24684a90f96e114e423081e40699b3ef8fa7d54716020
|
|
| MD5 |
a26aafe2d45bdd3df0a88760978b4070
|
|
| BLAKE2b-256 |
18bb9c60cf29b9a5982fb989e2f1fac5f31e3b3ad246238764091a324029d4e8
|
Provenance
The following attestation bundles were made for capkit-0.2.0.tar.gz:
Publisher:
release.yml on canforge/capkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
capkit-0.2.0.tar.gz -
Subject digest:
35e0337249f3d14493d24684a90f96e114e423081e40699b3ef8fa7d54716020 - Sigstore transparency entry: 2186931771
- Sigstore integration time:
-
Permalink:
canforge/capkit@1e134aedb99717d636e7289ce52db49c2c10f07f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/canforge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1e134aedb99717d636e7289ce52db49c2c10f07f -
Trigger Event:
push
-
Statement type:
File details
Details for the file capkit-0.2.0-py3-none-any.whl.
File metadata
- Download URL: capkit-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de7ca26192ccfe4a570da28cc6610878b2e0fb7bdc19fff5151eb0e66cd72e36
|
|
| MD5 |
c0d44f54aaf16f7e7676c0f77ae331fa
|
|
| BLAKE2b-256 |
72263663f384e556315f03ede510a421a9f2d75a18eb3f6cd9cc333cc061595c
|
Provenance
The following attestation bundles were made for capkit-0.2.0-py3-none-any.whl:
Publisher:
release.yml on canforge/capkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
capkit-0.2.0-py3-none-any.whl -
Subject digest:
de7ca26192ccfe4a570da28cc6610878b2e0fb7bdc19fff5151eb0e66cd72e36 - Sigstore transparency entry: 2186931786
- Sigstore integration time:
-
Permalink:
canforge/capkit@1e134aedb99717d636e7289ce52db49c2c10f07f -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/canforge
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1e134aedb99717d636e7289ce52db49c2c10f07f -
Trigger Event:
push
-
Statement type: