Run, monitor, and orchestrate batches of TRNSYS simulations
Project description
TRNRun
trnrun is a Python package that drives the TRNRun runner (trnrun.exe) to launch, monitor, and
manage TRNSYS simulations from Python. It runs multiple decks concurrently through a bounded worker
pool, mirrors each run's status, progress, and log events behind thread-safe objects, and renders a
live terminal display while simulations run, making it suitable for batch studies, parametric runs,
and job orchestration.
Each simulation is executed by its own trnrun.exe process, which handles machine-wide launch
serialization, startup detection, runtime monitoring, and log parsing on its own (see the runner
documentation). The manager consumes the runner's line-delimited JSON output from stdout and exposes
it through a typed, thread-safe Python API.
Requirements
- Windows
- Python >= 3.12
- TRNSYS v17 or v18
- Optional: Progress Tracker (Type3830)
Dependencies
Installation
PyPI:
pip install trnrun
Quick start
Run a single deck:
from trnrun import SimulationConfig, SimulationManager
config = SimulationConfig(watch_tmp=True)
with SimulationManager() as manager:
manager.add("path/to/deck.dck", config)
manager.wait()
or
from trnrun import SimulationConfig, SimulationManager
config = SimulationConfig(watch_tmp=True)
manager = SimulationManager()
manager.add("path/to/deck.dck", config)
manager.wait()
Run a folder of decks with bounded concurrency:
from pathlib import Path
from trnrun import SimulationConfig, SimulationManager
config = SimulationConfig(watch_tmp=True)
with SimulationManager(max_concurrent=4) as manager:
for deck in sorted(Path(r"C:\path\to\dck").glob("*.dck")):
manager.add(deck, config)
manager.wait()
print(f"succeeded: {len(manager.succeeded)} failed: {len(manager.failed)}")
Do your own results aggregation:
import time
from trnrun import SimulationConfig, SimulationManager
config = SimulationConfig(watch_tmp=True)
with SimulationManager(refresh_interval=0, block=False) as manager: # 0 disables the built-in display
sim = manager.add("example.dck", config)
while not sim.is_finished:
snap = sim.snapshot()
if snap.progress is not None:
print(f"{snap.progress.percent:6.1%} (N:{snap.notices} W:{snap.warnings} F:{snap.fatals})", end="\r")
time.sleep(1.0)
print(f"\nexit code: {sim.exit_code} succeeded: {sim.succeeded}")
API reference
Simulation states
Reported through Simulation.status:
| Status | Meaning |
|---|---|
PENDING |
Waiting to acquire the global mutex. |
LAUNCHING |
Mutex acquired; TrnEXE is being started. |
RUNNING |
Startup detection passed; the simulation is being monitored. |
DONE |
Completed successfully. |
CANCELLED |
The process exited before simulation time reached 100 %. |
ERROR |
Failed to launch, died during startup, or logged a fatal error. |
TIMEOUT |
Exceeded watch_timeout_ms (or detect_timeout_ms with kill_on_timeout). |
STALLED |
Simulation time stopped advancing for longer than stall_timeout_ms. |
CANCELLEDandSTALLEDrequirewatch_tmp=True(Type3830), since both are derived from simulation progress. Without it, an early exit is reported asDONE.
SimulationManager
Runs simulations using a bounded pool of worker threads.
SimulationManager(max_concurrent=DEFAULT_MAX_CONCURRENT, refresh_interval=1.0, block=True)
| Parameter | Type | Default | Description |
|---|---|---|---|
max_concurrent |
int |
cpu_count() - 1 |
Maximum number of simulations running at the same time. Must be >= 1. |
refresh_interval |
float |
1.0 |
Seconds between terminal display updates. A value <= 0 disables the display. |
block |
bool |
True |
If True, add() blocks until a worker is available; if False, returns immediately. |
| Member | Description |
|---|---|
add(deck_file, config) |
Start a simulation as soon as a worker is available and return its Simulation. |
wait(timeout=None) |
Block until every simulation added before this call has finished, or the timeout (seconds) expires. Returns True if all of them finished. |
simulations |
All added simulations, in creation order. |
succeeded() |
Simulations that completed successfully. |
failed() |
Simulations that finished without succeeding (fatal errors, non-zero exit, cancellation, launch failure). |
cancel() |
Request cancellation of every added simulation. |
shutdown(cancel=False, wait=True) |
Close the manager; further add() calls raise. With cancel=True running simulations are cancelled first; with wait=True the call blocks until the workers exit. |
SimulationManager is a context manager. Leaving the with block calls shutdown(), which waits
for running simulations to finish
Simulation
A handle for one runner process, normally obtained from SimulationManager.add(). TRNRun owns the
simulation state; this object only mirrors the latest events received on stdout, plus local process
bookkeeping (PID, exit code, cancellation).
All members are thread-safe. Each property acquires the internal lock separately, so two
consecutive reads may straddle an event - use snapshot() whenever a consistent multi-field view
is required.
| Member | Type | Description |
|---|---|---|
id |
int | None |
Identifier assigned by the manager. |
deck_path |
`str| Path | Deck (.dck) file passed to the runner. |
status |
StatusEvent | None |
Latest STATUS event. |
progress |
ProgressEvent | None |
Latest PROGRESS event. Requires watch_tmp=True. |
config |
ConfigEvent | None |
CONFIG event with simulation start / stop / step. |
logs |
list[LogEvent] |
Rolling window of LOG events (default: last 5 000). |
notices, warnings, fatals |
int |
Event counters, kept over the whole run — even after older events leave the rolling window. |
exit_code |
int | None |
None while running; the runner exit code afterwards. |
error |
str | None |
Python-side failure description (spawn failure, cancelled before start, ...). |
cancelled |
bool |
Whether cancel() was requested. |
pid |
int | None |
Runner process ID. |
is_running |
bool |
Runner process is alive. |
is_finished |
bool |
An exit code has been recorded. |
succeeded |
bool |
Success criteria under Exit codes. |
snapshot() |
SimulationSnapshot |
Consistent view of all of the above, captured under a single lock. |
cancel() |
None |
Request termination of the runner process. Safe to call before or after start. |
run() |
None |
Spawn the runner and consume stdout until it exits. Called by the manager's worker thread |
SimulationSnapshot
Frozen dataclass returned by Simulation.snapshot() with the fields id, deck_path, status,
progress, config_event, notices, warnings, fatals, log_count, exit_code, error,
and cancelled. Every field is captured in one critical section, so a consumer can never mix
state from either side of an event.
SimulationConfig
Dataclass describing how the runner is invoked. Each field maps to a trnrun.exe flag (passed as
--name:value), and the defaults mirror the runner's own CLI defaults. See the runner
documentation for full flag semantics.
| Field | Runner flag | Default | Description |
|---|---|---|---|
trnrun_path |
— | bundled trnrun.exe |
Runner executable to invoke. |
trnexe_path |
--trnexePath |
C:\TRNSYS18\Exe\TrnEXE64.exe |
TRNSYS executable (TrnEXE64.exe / TrnEXE.exe). |
gui_visibility |
--guiVisibility |
"hidden" |
TRNSYS window behavior: keep, auto, min, minAuto, hidden. |
wait_for_gui |
--waitForGui |
True |
Launch detection: wait for a TRNSYS GUI. |
wait_for_lst |
--waitForLst |
True |
Launch detection: wait for a specific string in the *.lst. |
wait_for_tmp |
--waitForTmp |
False |
Launch detection: wait for the *.tmp file. (Requires Type3830.) |
detect_timeout_ms |
--detectTimeout |
0 |
Timeout in ms for the detection stages; 0 = unlimited. |
extra_delay_ms |
--extraDelay |
0 |
Additional delay in ms after detection passes. |
poll_ms |
--pollMs |
100 |
Polling interval in ms for the output files and the process. |
watch_log |
--watchLog |
True |
Stream *.log entries as LOG events. |
watch_tmp |
--watchTmp |
False |
Stream *.tmp updates as CONFIG/PROGRESS events. (Type3830.) |
watch_timeout_ms |
--watchTimeout |
0 |
Maximum monitoring duration in ms; 0 = unlimited. |
stall_timeout_ms |
--stallTimeout |
0 |
Max wall-clock ms without progress; 0 = disabled. Needs watch_tmp. |
clean_on_success |
--clean |
False |
On success, delete *.tmp, *.log, *.lst, and *.PTI. |
kill_on_timeout |
--killOnTimeout |
False |
Kill TRNSYS on a detection or watch timeout. |
kill_on_stall |
--killOnStall |
False |
Kill TRNSYS when a stall is detected. |
severity |
--severity |
"Notice" |
Minimum log severity to emit: Notice, Warning, Fatal. |
write_log |
--writeLog |
False |
Also append every event to <deckFile>.jsonl. |
Display
A live terminal display is enabled by default: one line per simulation, refreshed every
refresh_interval seconds. Pass refresh_interval=0 (or any non-positive value) to disable it.
Recipes
Batch run with full monitoring
Python equivalent of the runner's batch recipe: runtime and stall monitoring per run, cleanup on success, and a summary at the end.
from pathlib import Path
from trnrun import SimulationConfig, SimulationManager
config = SimulationConfig(
watch_tmp=True,
watch_timeout_ms=300_000,
kill_on_timeout=True,
stall_timeout_ms=300_000,
kill_on_stall=True,
clean_on_success=True,
)
decks = sorted(Path(r"C:\path\to\dck").glob("*.dck"))
with SimulationManager(max_concurrent=4) as manager:
for deck in decks:
manager.add(deck, config)
manager.wait()
for sim in manager.failed:
print(f"{sim.deck_path} failed: exit={sim.exit_code} error={sim.error!r}")
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 Distributions
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 trnrun-0.4.0-py3-none-win_amd64.whl.
File metadata
- Download URL: trnrun-0.4.0-py3-none-win_amd64.whl
- Upload date:
- Size: 190.9 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0698ee14e97f8d7c6a6036e3d56226dc40f40aa2225f5d170fe9385fea08ea01
|
|
| MD5 |
9b1c299891d478245b8cf326adafd590
|
|
| BLAKE2b-256 |
6acf41d7821200cf47bc6b13e2b4fe8c21edef25f91911ea7c4f91692dfc84b1
|