Developers/Programming

Python scripts

The ctx API, startup, screen-open and button events, and periodic tasks.

2 min read

Scripts are project files scripts/<name>.py. Edit them in Studio (Scripts and tasks), with highlighting and syntax checks, or from an external editor.

Events

Event ctx.event When
Startup startup Once when Runtime starts, in the configured order
Screen open screen_open When opening or navigating to the screen
Button button Run script action
Periodic task task:<id> Every period, after the previous run finished

The ctx API

# Consistent snapshot taken when this run started.
if ctx.quality("Pump1.running") == "good":
    running = ctx.read("Pump1.running")
    print(f"Pump 1: {running}")

# State kept between runs of this script while Runtime is alive.
ctx.state["executions"] = ctx.state.get("executions", 0) + 1

# Request a write; validated and applied when the script ends without errors.
if ctx.read("Tank.level") > 90.0:
    ctx.write("Pump1.setpoint", 50.0)
Member Description
ctx.read(name) Value; raises if quality is not good
ctx.quality(name) good, uncertain or bad
ctx.write(name, value) Queues a write (max 1000 per run)
ctx.state JSON-serialisable dict per script
ctx.event Event that triggered the run
ctx.screen Source screen; empty for startup and tasks

If the script raises, its writes and ctx.state changes are discarded. print() output and errors appear in Executions.

Configuration

{
  "startup": ["startup"],
  "timeout_seconds": 10,
  "tasks": [
    {"id": "quality", "script": "check_quality", "interval_ms": 5000, "enabled": true}
  ]
}

Stored in automation.json. A screen adds "on_open": ["screen_open"]; a button "action": "script", "script": "name".

Execution

  • Every run uses a fresh Python process, with a 0.1 to 300 s limit (10 by default).
  • Events are serialised: a slow script delays others but never blocks Qt or acquisition.
  • Tasks never overlap and don't catch up on missed periods.

Trusted code

The separate process allows cancellation but is not a sandbox. Scripts run with the user's permissions and can import any installed library.

Example: start counter

# scripts/count_starts.py — task every 1000 ms
running = ctx.read("Pump1.running")
was_running = ctx.state.get("was_running", False)
if running and not was_running:
    ctx.write("Pump1.starts", ctx.read("Pump1.starts") + 1)
ctx.state["was_running"] = running

Runtime language

ctx.language returns the current language. ctx.set_language() accepts a declared project language and applies the change after the script succeeds and its commands are validated.

if ctx.language == "es":
    ctx.set_language("en")
Python scripts · abSCADA