FabyaVisionUser Manual
/

Python scripts

7 min readScripts

The structure of a Python script (Module and Action), the supported language and library, the scada object, differences from CPython, and permissions.

Scope of the language

Python scripts run in Live under the same rules as VBS and C (button event, scheduled task, tag-triggered task; in the background, without locking the interface). The language engine is written specifically for the product: no CPython installation and no internet access are required. The engine runs a subset of Python 3.12; its behavior and error messages have been tested by comparison with CPython 3.12.

Supported

  • Types: unlimited-size int, float, bool, str, bytes, bytearray, list, tuple, dict, set, frozenset, range, slices, multiple assignment and unpacking (a, *b = x), chained comparison, x if k else y.
  • Statements: if / elif / else, for and while (else, break, continue), try / except / else / finally, raise … from, assert, with, match / case, global, nonlocal, del.
  • Functions: default values, *args, **kwargs, keyword-only parameters, lambda, decorators, recursion (limit 1000), generators (yield, yield from), list / dictionary / set comprehensions.
  • Classes: multiple inheritance, super(), @property, @staticmethod, @classmethod, special methods; f-strings ({x!r}, {x:>10.2f}, {x=}), str.format, % formatting.
  • The ready-to-use part of the standard library (imported with import): math, random (the same number sequence as CPython), datetime, time, calendar, json, re, csv, statistics, collections, itertools, functools, string, textwrap, struct, base64, hashlib, decimal, fractions, enum, dataclasses, typing, io, uuid, heapq, bisect, contextlib and others. The full list is on the Library tab of the Reference panel.

Unsupported

If any of the following is used, the script stops with a clear message (NotImplementedError) and Studio warns in advance:

  • async / await / asyncio (not needed: tag writes, waits, database and file operations are awaited automatically)
  • eval, exec, compile, __import__, breakpoint, memoryview
  • complex numbers (1j), the @ operator (matrix multiplication), metaclasses and descriptors (except property)
  • threads and multiprocessing (threading, multiprocessing), network access (socket, http, urllib.request, ssl), ctypes
  • third-party packages (numpy, pandas, requests …): cannot be installed

Deliberate differences from CPython

  • The number and text format is independent of the Windows regional settings: str(1.5) is always '1.5' (unlike VBS).
  • Run-time errors carry the same message as Python's (str(e)); syntax errors are reported in Turkish.
  • Circular imports between project modules are not reliable; move shared functions to a third module.

Script types

Module
Functions are defined with def; they are brought into other Python code with import Betik_Adı. Module-level code runs once when the project opens (in dependency order). If no function is selected in an event or task, the function with the same name as the module runs; the Procedure / function list shows the functions of the module with their signatures.
Action
It runs from the beginning on every call. If the code contains def action(), that one runs; if not, def main(); if neither exists, the whole code is the body (a top-level return is allowed and is the return value).
Python module: in the toolbar, the function list with the def and class buttons; the number of functions at the bottom.123
Python module: in the toolbar, the function list with the def and class buttons; the number of functions at the bottom.
  1. PY — Python badge; type: Module.
  2. def / class — inserts an empty skeleton.
  3. Status strip — number of functions and classes.

The Parameters cell is locked in Python; function parameters are written in the code. The start template of a new script contains a function with the same name as the script in a module (def Tank_Kontrol(): pass) and def action(): return 0 in an action.

For code written directly in the event, use the Run Python code function: the code runs like an action body and no def is needed. Predefined names: Item (the object of the event; for a screen event, the screen), ScreenItems, Layers, DataSet, Parent (the screen of the event).

In a task triggered by On tag change, the new value of the tag is passed to the first parameter of the function as a Python type (Bool → bool, integer → int, Real → float, text → str). A function written without parameters can also be called.

Tag values and errors

StateResult
Reading Real / LReal tagsfloat: the value 50 arrives as 50.0; 1 and 1.0 are different types.
Reading a DateTime tagstr in ISO format (use tag.datetime to get a datetime).
Non-existent tagKeyError (scada.read("Ad", varsayılan) returns the default value instead of an exception).
A number exceeding the limitValueError (the lower / upper limit of the tag or the range of the integer type).
A value that does not match the type (e.g. text into a numeric tag)TypeError.
Disabled script permissionPermissionError (can be caught with try / except).

An unhandled error stops the script and is written to the event log in the format Modül / işlev, satır 12: ZeroDivisionError: division by zero; the program continues.

Examples

Module function and tag read / write:

# Bir tag'i okur, hesaplanan değeri başka bir tag'e yazar.
def Py_Tag_Oku_Yaz():
    seviye = scada.read("Tank1_Seviye")
    # Kalan boşluk (%) = 100 - seviye
    scada.write("Tank1_Bosluk", 100 - seviye)

Tag-triggered task function (the new value of the tag is the parameter):

def Py_Gorev_Islevi(yeni_deger):
    scada.write("Durum_Metni", f"Hız değişti: {yeni_deger}")
    if yeni_deger > 90:
        scada.write("Motor1_Ariza", True)

Error handling:

def Py_Hata_Yakalama():
    try:
        sonuc = scada.read("Toplam_Miktar") / scada.read("Parti_Adedi")   # adet 0 ise ZeroDivisionError
        scada.write("Hata_Metni", "")
    except ZeroDivisionError as hata:
        scada.write("Hata_Metni", f"Hata: {hata}")
        sonuc = 0
    scada.write("Parti_Ortalama", sonuc)

Shared module and import. In the Module script named Py_Ortak_Hesap_Modulu:

def olcekle(ham, alt, ust, ham_ust=27648.0):
    """Ham değeri alt ... ust aralığına çevirir."""
    return alt + (ust - alt) * ham / ham_ust

In another Python script:

import Py_Ortak_Hesap_Modulu as ortak

def Py_Ortak_Kullanim():
    scada.write("Sicaklik", ortak.olcekle(scada.read("Sicaklik_Ham"), -50.0, 150.0))

Action:

def action():
    seviye = scada.read("Tank1_Seviye")
    scada.write("Tank1_Durum", "Yüksek" if seviye >= 80 else "Normal")
    return 0

For other examples (wait_for, scada.db, open, json, re, dataclass), see the topic Script examples.

Limitations and points to note

  • 30-second limit: a call can compute for at most 30 seconds; scada.sleep and other wait operations do not count toward this time. A longer loop is interrupted.
  • Overlapping calls are skipped: a second call that arrives while the same trigger is still running is not executed.
  • os, shutil, glob, tempfile, subprocess, pyodbc and pathlib are not built in; write import before using them. If they are not imported, a NameError occurs and Studio gives an undefined name warning.
  • When starting a program, there is no way to wait for it or to capture its output (scada.run(bekle=True), subprocess.PIPE, check_output, Popen.wait, os.popen); there is no tempfile.mkstemp. There are no transactions (BEGIN / COMMIT) and no temporary tables in the database. The project file and the program folder cannot be written to.
  • HMIRuntime.Logging, AlarmLogs, DataLogs, Alarms, MenuToolBarConfig and writing object properties in a 3D screen are not supported.
  • Database, file and program execution has been tested only with a mock bridge; at the first trial in the field, with the permission enabled, try it in the real environment.
  • Scripts do not run in monitoring mode from a browser or the TV.

Related topics

FabyaVision 0.1.0 User Manual · 18 October 2026© Fabyatek Yazılım Bilişim Teknolojileri Ltd. Şti.