Skip to content

Logging

Espen Hovland edited this page Jun 5, 2026 · 2 revisions

Logging

Every Commander invocation can be recorded to a log file. This is invaluable for diagnosing issues in long-running automations and production-test rigs, where you want an audit trail of exactly which commands ran and when.

Enabling logging

Pass log_file_path (a pathlib.Path) to the Commander constructor. Each invocation is appended to that file with a timestamp.

from pathlib import Path
from pycommander import Commander

commander = Commander(serial_number="440055955", log_file_path=Path("pycommander.log"))

Because the Adapter and Target classes run through a Commander, the cleanest way to enable logging for high-level workflows is to build a logging-enabled Commander first and attach it:

from pathlib import Path
from pycommander import Adapter, Commander

commander = Commander(serial_number="440055955", log_file_path=Path("pycommander.log"))
adapter = Adapter(commander=commander, target_device="EFR32MG24")

What gets logged

The subprocess Runner writes an entry for each command it runs (both synchronous run and asynchronous open/streaming invocations), as well as for failures:

  • The executable and full argument list of each invocation.
  • A note when a command times out.
  • A note when a command fails, including the return code and Commander's output.

Each line is prefixed with a timestamp in YYYY-MM-DD HH:MM:SS.ffffff format:

[2026-06-05 14:51:02.123456] /path/to/commander-cli device info --device EFR32MG24 --serialno 440055955 --json
[2026-06-05 14:51:05.654321] Command failed with return code 254: <commander output>

Notes

  • The log file is appended to, never truncated — so a single file can accumulate history across many runs.
  • Entries are written as commands execute, which makes the log useful even if your script crashes partway through.
  • If the log file cannot be written, an exception is raised describing the problem; pick a path your process can write to.
  • Logging is independent of exceptions: failures are both logged and raised.

Tip: per-run log files

For production-test setups, a timestamped or per-DUT log filename keeps runs separate and easy to attach to test records:

import datetime
from pathlib import Path
from pycommander import Commander

stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
commander = Commander(serial_number="440055955", log_file_path=Path(f"logs/pc-{stamp}.log"))

Clone this wiki locally