PyA2L
ASAM ASAP2 Library for Python
Install / Use
/learn @christoph2/PyA2LREADME
Readme
|PyPI| |Python Versions| |License: LGPL v3+| |Code style: black| |Ask DeepWiki|
.. image:: pya2l_social.jpg :align: center
pyA2L is an ASAM MCD-2MC <https://www.asam.net/standards/detail/mcd-2-mc/>__ processing
library written in Python.
If you work with ECUs, ASAP2/A2L is the contract that describes what and how to measure or calibrate. pyA2L helps you parse once, inspect and validate programmatically, automate checks, and export back when needed — all from Python.
Contents
- About ASAM MCD-2 MC (ASAP2)
- What pyA2L offers
- Installation
- Getting Started (Quickstart)
- Command-line usage
- Tips
- Examples
- Compatibility
- Project links
- Contributing
- Code of Conduct
- License
- Changelog / Release notes
- Acknowledgements
About ASAM MCD-2 MC (ASAP2)
ASAM MCD-2 MC (ASAP2) is the ASAM standard that defines the A2L description format for ECU measurement signals and calibration parameters. In practice, the A2L acts as a contract between ECU software and tools so different vendors can consistently locate data in memory and convert raw values into physical engineering units. Runtime transport (e.g., CCP/XCP) is out of scope of the standard.
For an authoritative overview of the standard, see the ASAM page: https://www.asam.net/standards/detail/mcd-2-mc/
What pyA2L offers
- Parse .a2l files and persist them as compact, queryable SQLite databases (.a2ldb) to avoid repeated parse costs.
- Programmatic access to ASAP2 entities via SQLAlchemy ORM models (MODULE, MEASUREMENT, CHARACTERISTIC, AXIS_DESCR, RECORD_LAYOUT, COMPU_METHOD/COMPU_TAB, UNIT, FUNCTION, GROUP, VARIANT_CODING, etc.).
- Rich inspection helpers in pya2l.api.inspect (e.g., Characteristic, Measurement, AxisDescr, ModPar, ModCommon) to compute shapes, axis info, allocated memory, conversions, and more.
- Creator API in pya2l.api.create to programmatically build or augment A2L content (PROJECT, MODULE, MEASUREMENT, CHARACTERISTIC, COMPU_METHOD, AXIS_PTS, RECORD_LAYOUT, GROUP, FUNCTION, etc.).
- Validation utilities (pya2l.api.validate) to check common ASAP2 rules and project-specific consistency.
- Export .a2ldb content back to A2L text or JSON when needed.
- Building blocks for automation: reporting, quality gates, CI checks, and integration with CCP/XCP workflows.
Supported ASAP2 version: 1.7.1
Why pyA2L?
- Parse once, query fast: Avoid repeated parser runs by working from SQLite.
- Powerful model: Use SQLAlchemy ORM to navigate ASAP2 entities naturally.
- Beyond parsing: Inspect derived properties, validate consistency, and export back to A2L.
- Automate: Integrate with CI to enforce quality gates on A2L content.
Design highlights
- SQLite-backed storage (.a2ldb) with SQLAlchemy models
- C++ parser (ANTLR4-based) for fast parsing (2.5 MB/s)
- Adaptive flush strategy automatically tunes performance (10% speedup for large files)
- High-level inspection helpers in
pya2l.api.inspect - Creator API in
pya2l.api.createfor programmatic A2L generation - Validator framework in
pya2l.api.validateyielding structured diagnostics - Export to A2L text or JSON format with complete roundtrip fidelity
- Optional CLI (
a2ldb-imex) for import/export tasks - Concurrent access via SQLite WAL mode (multiple readers during export)
Learn more about the standard at the ASAM website: https://www.asam.net/standards/detail/mcd-2-mc/wiki/
Installation
-
Via
pip:shell $ pip install pya2ldbIMPORTANT: Package-name ispya2ldbNOTpya2l!!! -
From Github:
- Clone / fork / download
pyA2Ldb repository <https://github.com/christoph2/pya2l>__.
- Clone / fork / download
Getting Started (Quickstart)
Parse once, work from SQLite thereafter.
Import a .a2l file and persist it as .a2ldb (SQLite):
.. code:: python
from pya2l import DB
db = DB() session = db.import_a2l( "ASAP2_Demo_V161.a2l", # Optional: # encoding="utf-8", # default is latin-1 # progress_bar=False, # silence the progress meter # loglevel="ERROR", # also suppresses progress )
Creates ASAP2_Demo_V161.a2ldb in the working directory
- Open an existing .a2ldb without re-parsing:
.. code:: python
from pya2l import DB
db = DB() session = db.open_existing("ASAP2_Demo_V161") # extension .a2ldb is implied
Query with SQLAlchemy ORM - List all measurements ordered by name with address and data type:
.. code:: python
from pya2l import DB import pya2l.model as model
db = DB() session = db.open_existing("ASAP2_Demo_V161") measurements = ( session.query(model.Measurement) .order_by(model.Measurement.name) .all() ) for m in measurements: print(f"{m.name:48} {m.datatype:12} 0x{m.ecu_address.address:08x}")
High-level inspection helpers - Use convenience wrappers from pya2l.api.inspect to access derived info:
.. code:: python
from pya2l import DB from pya2l.api.inspect import Characteristic, Measurement, AxisDescr
db = DB() session = db.open_existing("ASAP2_Demo_V161") ch = Characteristic(session, "ASAM.C.MAP.UBYTE.IDENTICAL") print("shape:", ch.dim().shape) print("element size:", ch.fnc_element_size(), "bytes") print("num axes:", ch.num_axes())
me = Measurement(session, "ASAM.M.SCALAR.UBYTE.IDENTICAL") print("is virtual:", me.is_virtual())
axis = ch.axisDescription("X") print("axis info:", axis.axisDescription("X"))
Create A2L content programmatically - Use the Creator API to build or augment A2L databases:
.. code:: python
from pya2l import DB from pya2l.api.create import ( ProjectCreator, ModuleCreator, MeasurementCreator, CharacteristicCreator, CompuMethodCreator )
db = DB() session = db.open_create("MyProject.a2ldb")
Create project and module
pc = ProjectCreator(session) project = pc.create_project("MyProject", "Demo ECU Project")
mc = ModuleCreator(session) module = mc.create_module("MyModule", "Demo Module", project=project)
Add a conversion method
cmc = CompuMethodCreator(session) cm = cmc.create_compu_method( "CM_Voltage", "Voltage conversion", "LINEAR", "%6.3", "V", module_name="MyModule" ) cmc.add_coeffs_linear(cm, offset=0.0, factor=0.01) # y = 0.01*x + 0
Add a measurement
mec = MeasurementCreator(session) meas = mec.create_measurement( "BatteryVoltage", "Battery voltage in Volts", "UWORD", "CM_Voltage", resolution=1, accuracy=0.1, lower_limit=0.0, upper_limit=20.0, module_name="MyModule" ) mec.add_ecu_address(meas, 0x1000)
Add a characteristic (calibration parameter)
cc = CharacteristicCreator(session) char = cc.create_characteristic( "InjectionMap", "Fuel injection map", "MAP", 0x2000, "RL_InjMap", 0.0, "CM_Voltage", 0.0, 100.0, module_name="MyModule" )
mc.commit() db.close()
Validate your database
.. code:: python
from pya2l import DB from pya2l.api.validate import Validator
db = DB() session = db.open_existing("ASAP2_Demo_V161") vd = Validator(session) for msg in vd(): # iterate diagnostics # msg has fields: type (Level), category (Category), diag_code (Diagnostics), text (str) print(msg.type.name, msg.category.name, msg.diag_code.name, "-", msg.text)
Export back to A2L or JSON
.. code:: python
from pya2l import export_a2l
Export to A2L text format
export_a2l("ASAP2_Demo_V161", "exported.a2l")
Or export to JSON for further processing
from pya2l.imex.json_exporter import export_json export_json("ASAP2_Demo_V161.a2ldb", "exported.json")
Tips
- Default import encoding is latin-1; override
encoding=if your file differs. - Silence the progress meter via
progress_bar=Falseorloglevel="ERROR". - Python package name is
pya2ldb(notpya2l). - See
howto <./howto.rst>__ for Excel export and other short recipes.
Examples
- See
pya2l/examplesfor sample A2L files and scripts. - The Sphinx docs contain a fuller tutorial and HOWTO guides.
Create API and coverage parity
pyA2L offers a Creator API in pya2l.api.create to programmatically build or augment A2L content. The project’s goal is coverage parity: everything you can query via pya2l.api.inspect is intended to be creatable via pya2l.api.create.
Example: creating common entities
.. code:: python
from pya2l import DB from pya2l.api.create import ModuleCreator from pya2l.api.inspect import Module
Open or create a database
session = DB().open_create("MyProject.a2l") # or .a2ldb
mc = ModuleCreator(session)
Create a module
mod = mc.create_module("DEMO", "Demo ECU module")
Units and conversions
temp_unit = mc.add_unit(mod, name="degC", long_identifier="Celsius", display="°C", type_str="TEMPERATURE") ct = mc.add_compu_tab(mod, name="TAB_NOINTP_DEMO", long_identifier="Demo Tab", conversion_type="TAB_NOINTP", pairs=[(0, 0.0), (100, 1.0)], default_numeric=0.0)
Frames and transformers
fr = mc.add_frame(mod, name="FRAME1", long_identifier="Demo frame", scaling_unit=1, rate=10, measurements=["ENGINE_SPEED"]) tr = mc.add_transformer(mod, name="TR1", version="1.0", executable32="tr32.dll", executable64="tr64.dll", timeout=1000, trigger="ON_CHANGE", inverse="NONE", in_objects=["ENGINE_SPEED"], out_objects=["SPEED_PHYS"])
Typedefs and instances
ts = mc.add_typedef_structure(mod, name="TSig", long_identifier="Signal", size=8) mc.add_structure_component(ts, name="raw", typedefName="UWORD",
Related Skills
node-connect
343.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
90.0kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
90.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
343.1kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
