Python interface to DesignBuilder's command-line driver — typed /process= commands,
subprocess execution, process discovery, and diagnostics-log parsing.
DesignBuilder is a Windows GUI app, but it exposes a /process= argument
that runs a sequence of commands non-interactively and exits. db-process
wraps that surface in real Python: dataclass commands instead of stringly-typed
flags, a ProcessChain builder, blocking and non-blocking runners, helpers
to find/kill the process, and a parser for the rolling diagnostics logs
DesignBuilder writes under %LOCALAPPDATA%.
pip install db-process
# or, from the cloned repo:
pip install -e .[dev]Requires Python 3.10+ and psutil. DesignBuilder itself only runs on Windows;
on other platforms, the package imports fine but run() and the process
helpers will raise FileNotFoundError.
from db_process import ProcessChain, Screen, run
chain = (
ProcessChain()
.use_sim_manager()
.switch_screen(Screen.SIMULATION)
.sim_start_date(1, 1)
.sim_end_date(31, 12)
.change_attribute("OccupancyValue", 0.5)
.run()
)
result = run("models/office.dsb", chain, timeout=600)
print(result.success, result.duration_seconds)from db_process import eplus_simulation, run
# A pre-built ProcessChain for "open model, run EnergyPlus, close".
result = run("models/office.dsb", eplus_simulation())Other factories: sbem_calculation, export_xml, heating_and_cooling_design,
daylighting, cfd_simulation.
from db_process import run_async
handle = run_async("models/office.dsb")
# Block until DesignBuilder finishes its work and CPU drops, then kill it.
handle.kill_when_idle(idle_threshold=10, cpu_threshold=0.1)kill_when_idle is the workaround for runs where DesignBuilder finishes the
calculation but doesn't exit — common with the GUI Sim Manager path.
db-process status # is DesignBuilder running? show pid + exe path
db-process open # launch DesignBuilder
db-process open path/to.dsb # launch with a model
db-process close # kill any running DesignBuilder
db-process restart [model] # close + open (with a 1.5 s settle)
db-process diag list # list recent diagnostic logs (newest first)
db-process diag latest # print a one-paragraph summary of the newest log
db-process diag latest --errors # also list every error line found
db-process diag summary <path> # summarise a specific logdb-process is the entry point installed by the package; you can also run it
as python -m db_process.
from db_process import (
# Executable discovery
find_designbuilder, # () -> Path
# Process status
is_running, find_process, status, # status() -> ProcessStatus
kill_process, kill_when_idle,
ProcessStatus, # is_running, pid, exe_path
# Run
run, run_async, RunHandle, RunResult,
# Command model
ProcessChain, Screen,
SwitchScreen, RunCalculation, TabChange,
SimStartDate, SimEndDate, ChangeAttributeValue,
ExternalCommand, ImportModelData, ImportLibraryData,
ExportAsXML, UseSimManager, NoClose,
# Convenience factories
eplus_simulation, sbem_calculation, export_xml,
heating_and_cooling_design, daylighting, cfd_simulation,
# Diagnostics logs
DiagnosticsLog, find_logs, latest_log,
parse_filename_timestamp, DEFAULT_DIAGNOSTICS_DIR,
)find_designbuilder(exe_path=None) resolves DesignBuilder.exe in this order:
- The explicit
exe_pathargument, if given. DESIGNBUILDER_EXEenvironment variable.C:\Program Files (x86)\DesignBuilder\DesignBuilder.exe, thenC:\Program Files\DesignBuilder\DesignBuilder.exe.- The system
PATH(shutil.which("DesignBuilder")).
Raises FileNotFoundError with a hint to set DESIGNBUILDER_EXE if none match.
status() is a one-shot snapshot:
from db_process import status
s = status()
# ProcessStatus(is_running=True, pid=12345, exe_path='C:\\...\\DesignBuilder.exe')
if not s.is_running and s.exe_path:
# Discovered but not running — safe to launch.
...exe_path is populated regardless of whether the process is running, so
callers can decide whether to launch without a second find_designbuilder
call.
ProcessChain is a fluent builder for the /process= command sequence
documented in DesignBuilder Help. Example output of chain.to_string():
/process=UseSimManager, miGSS, SimStartDate 1 1, SimEndDate 31 12,
ChangeAttributeValue OccupancyValue 0.5, miTUpdate
Every command is also exposed as a plain dataclass, so you can construct chains without the builder when that's clearer.
DesignBuilder writes a per-session diagnostics log to
%LOCALAPPDATA%\DesignBuilder\Diagnostics\ named like
DesignBuilder_diagnostic_2026-04-23_15-12-08.txt. DiagnosticsLog
parses one of those files into a structured object:
from db_process import latest_log, DiagnosticsLog
log = DiagnosticsLog.from_file(latest_log())
print(log.summary())
print(log.is_complete, log.duration, log.error_count)
for line_no, text in log.errors:
print(f"L{line_no}: {text}")Error detection uses word-boundary matching (error, failed, exception,
fatal, crash) plus a small negative list to suppress known benign markers
(e.g. the GL_KHR_no_error OpenGL extension).
- DesignBuilder: any version that supports the
/process=argument. Tested against the v25.1 / v26.1 lines. - Python: 3.10+.
- OS: Windows for live runs. The command model and diagnostics parser are pure Python and import on any platform — useful for unit tests on Linux CI.
pip install -e .[dev]
pytest
ruff check .Tests are split by area:
| File | Covers |
|---|---|
test_commands.py |
ProcessChain building + every command's to_string() |
test_executable.py |
find_designbuilder resolution order |
test_status.py |
status / ProcessStatus |
test_diagnostics.py |
log parsing, error detection, filename timestamps |
test_cli.py |
CLI argparse wiring (mocked subprocess) |