Zum Hauptinhalt springen

Engineering · Werkzeuge

TIA Portal mit Python steuern: Mechanik und Grenzen

Wie pythonnet die Brücke zu TIA Portal Openness schlägt, warum .NET 6 ausscheidet, was V21 bricht — und wo Python an eine harte Grenze stößt.

Stand:

Zwischen einem Python-Skript und dem TIA Portal liegt keine Schnittstelle, sondern eine Sprachgrenze. TIA Portal Openness ist eine .NET-Programmierschnittstelle: Das Systemhandbuch nennt als Voraussetzung Visual Studio mit dem .NET-Framework-SDK, als nötiges Wissen fortgeschrittene C#-Kenntnisse, und es hält ausdrücklich fest, dass sämtliche Codebeispiele der Dokumentation in C#-Syntax geschrieben sind. Python kommt darin an keiner Stelle vor.

Trotzdem funktioniert der Weg, und er wird benutzt. Die verbreiteten Beispiele zeigen zwanzig Zeilen und schweigen über die Reihenfolge, in der sie stehen müssen, über die Laufzeit, an die sie gebunden sind, und über das, was seit TIA Portal V21 nicht mehr stimmt.

Dieser Artikel beschreibt die Mechanik der Brücke, die Reihenfolge ihres Aufbaus, die Fallen auf dem Weg — und die Stellen, an denen Python an eine Grenze stößt, die kein Kniff verschiebt. Was sich mit V21 an Openness selbst geändert hat, steht in TIA Portal Openness V21; hier geht es um die Python-Seite davon. Und weil die Verwechslung häufig ist: Openness bearbeitet das Engineering, also das Projekt. Werte aus einer laufenden Steuerung zu lesen ist eine andere Aufgabe und läuft über ganz andere Wege.

ÜberblickVier Schichten zwischen Skript und Projekt.Der Aufruf wandert durch den eigenen Prozess nach unten — und überschreitet erst ganz zuletzt eine Prozessgrenze, an der zwei Sperren sitzen.
SACKGASSEWEG DES AUFRUFSWORAUF ES ANKOMMTPYTHON-PROZESSpython.exe · CPython 3.10–3.141Auswertung, Dateien, Berichte —wofür man Python haben willPYTHONNET · CLR-LOADER3.1.0 · 0.3.1 — die Brücke2Laufzeitwahl vor dem erstenimport clr — danach ist sie fest.NET 6 · .NET 8kein Remoting — Sackgasse.NET FRAMEWORK 4.8Laufzeit im selben Prozess3Diese Laufzeit ist gesetzt,nicht gewähltOPENNESS-ASSEMBLIESSiemens.Engineering4bis V20: Siemens.Engineering.dllab V21: …Base.dll unter net48PROZESSGRENZE · ZWEI SPERRENWindows-Gruppe für OpennessSicherheitsabfrage im TIA PortalTIA PORTAL · EIGENER PROZESSProjekt · Bausteine · Variablentabellenje Prozess genau eine TIA-Version5An eine laufende Instanz anhängen,nicht jedes Mal neu starten
  • Weg des Aufrufs
  • Sperre oder Sackgasse
  • Nummerierte Stufe · Ziel des Aufrufs

Eigene Darstellung nach der Openness-Dokumentation zu V20 und V21, dem Quelltext von pythonnet und clr-loader sowie Microsofts Hinweis zum Wegfall von .NET Remoting, geprüft am 26.08.2026.

Die Brücke und ihre Reihenfolge

Die Verbindung stellt pythonnet her, zusammen mit seinem Unterbau clr-loader. Beides sind Gemeinschaftsprojekte unter MIT-Lizenz, beides ist nicht TIA-spezifisch: pythonnet lädt eine .NET-Laufzeit in den laufenden Python-Prozess und macht .NET-Typen als Python-Objekte sichtbar. Was danach geladen wird — Openness oder etwas ganz anderes — ist der Brücke gleichgültig.

Genau daraus folgt der erste und am häufigsten übersehene Punkt: Welche Laufzeit geladen wird, entscheidet sich vor dem ersten Zugriff, nicht danach.

Der zweite Punkt nimmt Arbeit ab, die die C#-Beispiele noch von Hand erledigen: pythonnet bringt einen eigenen Assembly-Auflöser mit. Bleibt eine Assembly beim Laden unauffindbar, durchsucht er jeden Eintrag aus sys.path nach einer gleichnamigen DLL. Es genügt also, das Openness-Verzeichnis an den Suchpfad zu hängen — die abhängigen Siemens-Assemblies werden dann mitgefunden, ohne dass man selbst einen Auflöser schreibt.

Der kürzeste vollständige Weg: Laufzeit wählen, Assemblies finden lassen, anhängen.
bruecke.pyPython
"""Laufzeit wählen, Assemblies finden lassen, an eine laufende Instanz anhängen."""

import os
import sys

# 1) Laufzeit wählen — VOR allem, was clr anfasst.
from pythonnet import load

load("netfx")

import clr  # noqa: E402  — der Import steht bewusst NACH load()

# 2) Das Openness-Verzeichnis auf sys.path legen.
#    pythonnet hat einen eigenen Assembly-Auflöser: Er durchsucht jeden Eintrag
#    aus sys.path nach einer gleichnamigen DLL. Damit werden auch die
#    abhängigen Siemens-Assemblies gefunden — ein eigener Auflöser ist hier
#    nicht nötig.
TIA = "V20"
OPENNESS_DIR = rf"C:\Program Files\Siemens\Automation\Portal {TIA}\PublicAPI\{TIA}"
if not os.path.isdir(OPENNESS_DIR):
    raise SystemExit(f"Openness-Verzeichnis nicht gefunden: {OPENNESS_DIR}")
sys.path.append(OPENNESS_DIR)

clr.AddReference("Siemens.Engineering")

import Siemens.Engineering as tia                              # noqa: E402
from System.Runtime.InteropServices import RuntimeInformation  # noqa: E402

# 3) Kontrolle, bevor irgendetwas Fachliches passiert.
#    Eine konkrete Framework-Version lässt sich über die Brücke nicht anfordern;
#    get_runtime_info() meldet die Version als undefiniert. Wer 4.8 nachweisen
#    will, fragt die Laufzeit selbst.
print("CLR:   ", RuntimeInformation.FrameworkDescription)   # .NET Framework 4.8.xxxx
print("Python:", sys.version.split()[0], "| 64 Bit:", sys.maxsize > 2**32)

# 4) An eine laufende Instanz anhängen, statt eine neue zu starten.
prozesse = list(tia.TiaPortal.GetProcesses())   # statisch, braucht keine Instanz
if not prozesse:
    raise SystemExit("Keine laufende TIA-Portal-Instanz gefunden.")

for p in prozesse:
    print(f"  PID {p.Id} | Mode {p.Mode} | Projekt {p.ProjectPath}")

# Im Betrieb nicht den ersten nehmen, sondern die Prozessnummer übergeben:
# prozess = tia.TiaPortal.GetProcess(pid)
portal = prozesse[0].Attach()      # löst die Sicherheitsabfrage im TIA Portal aus
try:
    projekt = portal.Projects[0]
    print("Projekt:", projekt.Path.FullName)
finally:
    portal.Dispose()               # ab pythonnet 3.1.0 auch als with-Block möglich

Gegen TIA V17 bis V20 geschrieben. Unter V21 greift dieser Pfad ins Leere — dort heißt die Basis-Assembly Siemens.Engineering.Base.dll und liegt ein Verzeichnis tiefer. Syntaktisch geprüft, nicht gegen ein reales TIA Portal ausgeführt.

Warum .NET 6 nicht in Frage kommt

Die naheliegende Idee, die Brücke einfach auf eine moderne .NET-Laufzeit zu stellen, scheitert nicht an einer Einstellung, sondern an der Bauweise von Openness.

Das erklärt zugleich, warum die Wahl der Laufzeit so streng ist. Sie ist nicht eine Einstellung unter vielen, sondern die Voraussetzung dafür, dass die Openness-Assembly überhaupt geladen werden kann.

Datenblatt

Pfade, Schlüssel und Versionsstände.

Basis-Assembly bis TIA V20
Siemens.Engineering.dllDirekt im Verzeichnis der jeweiligen Openness-Version
Basis-Assembly ab TIA V21
Siemens.Engineering.Base.dllEin Verzeichnis tiefer, im Unterordner net48
PublicKeyToken V20
d29ec89bac048f84
PublicKeyToken V21
29bfe5fdf4ba5d3b
Registry-Wurzel
HKLM · SOFTWARE · Siemens · Automation · OpennessZwingend in der 64-Bit-Sicht lesen, sonst zeigt der Zugriff in den WOW6432Node
Ziel-Laufzeit
.NET Framework 4.8Eine konkrete Framework-Version lässt sich über die Brücke nicht anfordern
CPython für pythonnet 3.1.0
3.10 bis 3.14Version 3.1.0 hat die Unterstützung für 3.7 bis 3.9 fallen gelassen
CPython für das Siemens-Paket
3.12, 3.13, 3.14Nur 64 Bit, und je Interpreter genau eine passende Datei
Bitness der aufrufenden Anwendung
32 Bit, 64 Bit oder Any CPUSo die Openness-Dokumentation — das Siemens-Wheel gibt es dagegen nur für 64 Bit

Pfade, Schlüssel und Token aus der Openness-Dokumentation zu V20 und V21 sowie dem Siemens-Beispiel zur Assembly-Auflösung; Versionsangaben aus den Paket-Metadaten, geprüft am 26.08.2026.

Der Bruch mit TIA Portal V21

Bis V20 genügte ein fest verdrahteter Pfad auf eine einzige Datei. Genau so steht es in praktisch jedem Beispiel, das man zu diesem Thema findet — und genau das ist der Grund, warum diese Beispiele auf einer V21-Installation nichts mehr finden.

Die Zäsur

Was V21 an der Python-Seite ändert.

Bis V20

Eine Assembly, ein Pfad

Siemens.Engineering.dll, direkt im Verzeichnis der jeweiligen Openness-Version.

  • Ein fest verdrahteter Pfad auf eine einzige Datei
  • PublicKeyToken d29ec89bac048f84
  • Kein Zwischenverzeichnis für die Ziel-Laufzeit

Der Stand bis einschließlich V20

Ab V21

Modulare Assemblies unter net48

Eine Basis-Assembly plus getrennte Bibliotheken, ein Verzeichnis tiefer.

  • Auflösung auf Siemens.Engineering.Base statt auf Siemens.Engineering
  • PublicKeyToken 29bfe5fdf4ba5d3b
  • Unterverzeichnis net48 für die Ziel-Laufzeit
  • Freigabeliste mit Pfad, Änderungsdatum und Prüfsumme der aufrufenden Anwendung

Anwendungen müssen angepasst werden

Deshalb gehört der Pfad nicht ins Skript, sondern in eine Abfrage: Die Registry ist die einzige Quelle, die beide Ablagen kennt — und sie ist zugleich der Weg, den Siemens für die eigene .NET-Welt empfiehlt.

Die Freigabeliste hat für die Python-Seite eine Nebenwirkung, die selten ausgesprochen wird. Identifiziert wird die aufrufende Anwendung, nicht das Skript — und die aufrufende Anwendung ist bei diesem Weg der Interpreter. Eine einmal erteilte Freigabe gilt damit für jedes Python-Skript auf dieser Maschine, und jede Aktualisierung des Interpreters entwertet den Eintrag, weil sich die Prüfsumme ändert. Diese Schlussfolgerung zieht die Siemens-Dokumentation nicht selbst; sie folgt aus der dort beschriebenen Mechanik.

Beide Ablagen aus der Registry lesen, statt einen Pfad zu raten.
openness_pfad.pyPython
r"""Openness-Installationen aus der Registry lesen — beide Ablagen:

  TIA V14 bis V20 : ...\PublicAPI\Vxx\Siemens.Engineering.dll
  TIA V21         : ...\PublicAPI\V21\net48\Siemens.Engineering.Base.dll
"""

import winreg

WURZEL = r"SOFTWARE\Siemens\Automation\Openness"

# Die 64-Bit-Sicht ist Pflicht. Ohne sie landet ein 32-Bit-Prozess im
# WOW6432Node und findet den Schlüssel nicht — die Meldung sieht dann aus,
# als wäre Openness gar nicht installiert.
SICHT = winreg.KEY_READ | winreg.KEY_WOW64_64KEY


def _unterschluessel(schluessel):
    i = 0
    while True:
        try:
            yield winreg.EnumKey(schluessel, i)
        except OSError:
            return
        i += 1


def openness_installationen():
    """Liefert [(TIA-Version, Openness-Version, Ziel-Laufzeit oder None, Pfad), ...]."""
    gefunden = []
    try:
        wurzel = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, WURZEL, 0, SICHT)
    except FileNotFoundError:
        return gefunden

    with wurzel:
        for tia_version in _unterschluessel(wurzel):
            if tia_version == "AllowList":      # ab V21 die Freigabeliste, keine Version
                continue
            try:
                api = winreg.OpenKey(wurzel, rf"{tia_version}\PublicAPI", 0, SICHT)
            except FileNotFoundError:
                continue

            with api:
                for openness_version in _unterschluessel(api):
                    with winreg.OpenKey(api, openness_version, 0, SICHT) as ver:
                        # V14 bis V20: der Wert hängt direkt an diesem Schlüssel.
                        try:
                            pfad, _ = winreg.QueryValueEx(ver, "Siemens.Engineering")
                            gefunden.append((tia_version, openness_version, None, pfad))
                            continue
                        except FileNotFoundError:
                            pass

                        # Ab V21: je Ziel-Laufzeit ein Unterschlüssel, etwa net48.
                        for tfm in _unterschluessel(ver):
                            with winreg.OpenKey(ver, tfm, 0, SICHT) as tfm_key:
                                try:
                                    pfad, _ = winreg.QueryValueEx(
                                        tfm_key, "Siemens.Engineering.Base"
                                    )
                                except FileNotFoundError:
                                    continue
                                gefunden.append(
                                    (tia_version, openness_version, tfm, pfad)
                                )
    return gefunden


for eintrag in openness_installationen():
    print(eintrag)

Der Weg über die Registry ist der einzige, der ein Skript über V17 bis V21 hinweg am Leben hält. Die Zeile mit der 64-Bit-Sicht ist kein Beiwerk: Aus einem 32-Bit-Prozess heraus meldet der Zugriff sonst, Openness sei nicht installiert — obwohl es installiert ist.

Anhängen statt starten

Ein Skript kann das TIA Portal selbst starten, auch ohne Bedienoberfläche. Der interessantere Fall ist der andere: Es hängt sich an eine bereits laufende Instanz, in der jemand ein Projekt geöffnet hat.

Dafür gibt es eine statische Methode, die alle laufenden Instanzen aufzählt, und eine zweite, die eine Instanz über ihre Prozessnummer greift. Der eigentliche Zugriff ist dann ein Aufruf, der die Verbindung zurückgibt. Drei Einschränkungen gehören dazu, und alle drei sind hart:

  • Ein Prozess sieht nur eine TIA-Version. Die Aufzählung liefert ausschließlich Prozesse der Version, zu der die geladene Assembly gehört. Mehrere Openness-Versionen in derselben Anwendungsdomäne sind laut Siemens nicht unterstützt. Wer V18 und V20 nebeneinander betreut, braucht zwei Prozesse — nicht zwei Bibliotheken.
  • Loslassen ist nicht zumachen. Eine übernommene Instanz wird getrennt, nicht geschlossen. Wer sich an das TIA Portal einer Kollegin hängt und anschließend die Schließen-Funktion ruft, schließt ihr das Programm — mit allem, was darin offen war.
  • Ein geschlossenes TIA Portal beendet den Lauf. Schließt jemand das Programm, während ein Skript daran arbeitet, meldet Openness eine nicht behebbare Ausnahme — der Lauf ist damit vorbei.

Eine belastbare Verbindung, Schritt für Schritt

Anleitung

Vom leeren Skript zur Verbindung, die auch morgen noch steht.

Die Arbeit liegt nicht im Code, sondern in der Umgebung. Wer die Reihenfolge umdreht, sucht Fehler an der falschen Stelle — meistens im Skript, wo keiner ist.

  1. Die Umgebung festschreiben, bevor Code entsteht

    PowerShell

    Drei Dinge entscheiden über Erfolg oder Fehlersuche, und keines davon steht im Skript: welcher Interpreter läuft, ob eine Laufzeitvorgabe in der Umgebung steht, und ob der ausführende Benutzer überhaupt hineindarf.

    Interpreter, Umgebungsvorgabe und Gruppenmitgliedschaft prüfen.
    umgebung.ps1PowerShell
    # Welche Interpreter sind installiert, und welcher davon ist 64 Bit?
    py -0p
    py -3.12 -c "import sys; print(sys.version); print('64 Bit:', sys.maxsize > 2**32)"
    
    # Steht eine Laufzeitvorgabe in der Umgebung? Sie schlägt die eigene Wahl im
    # Skript, sobald irgendein Modul vor der eigenen Zeile 'clr' importiert.
    $env:PYTHONNET_RUNTIME
    
    # Weg 1: die Brücke installieren.
    py -3.12 -m pip install "pythonnet==3.1.0"
    
    # Weg 2: das Siemens-Wheel aus dem Download des Beitrags 109742322 — immer mit
    # dem Interpreter installieren, der es später benutzt. Die Wheels sind an den
    # CPython-Tag gebunden; cp312 und cp313 sind nicht austauschbar.
    py -3.12 -m pip install .\install\siemens_tia_scripting-1.4.3-cp312-cp312-win_amd64.whl
    
    # Gehört der ausführende Benutzer zur nötigen Windows-Gruppe?
    net localgroup "Siemens TIA Openness"
  2. Die Laufzeit wählen und die Assemblies auffindbar machen

    Python

    Die Laufzeitwahl steht als erste Anweisung, die Ergänzung des Suchpfads direkt danach — beides wie im Beispiel weiter oben. Wer den von Siemens vorgeschlagenen Weg über eine Konfigurationsdatei bevorzugt, kann das auch aus Python, muss dafür aber eine eigene, benannte Anwendungsdomäne anlegen.

    Der von Siemens vorgeschlagene Weg: die Assembly über eine Konfigurationsdatei finden.
    openness.configXML
    <?xml version="1.0"?>
    <!-- Beispiel für TIA Portal V20. Die Datei liegt neben dem Skript. -->
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Siemens.Engineering"
                              culture="neutral"
                              publicKeyToken="d29ec89bac048f84" />
            <codeBase version="20.0.0.0"
                      href="FILE://C:\Program Files\Siemens\Automation\Portal V20\PublicAPI\V20\Siemens.Engineering.dll" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

    Aus Python wirkt diese Datei nur mit einer eigenen, benannten Anwendungsdomäne — die Brücke braucht dafür einen zusätzlichen Parameter. Fehlt er, wird die Datei stillschweigend ignoriert; clr-loader begründet das damit, dass sich die Konfiguration der Wurzeldomäne nicht steuern lässt. Für V21 sind Name, Token und Pfad anzupassen.

    Für den Regelfall ist der Weg über den Suchpfad einfacher. Für ein Skript, das mehrere TIA-Stände bedienen soll, ist die Registry-Abfrage der einzig tragfähige.

  3. Anhängen — und genau das treffen, was gemeint ist

    Openness

    Ab hier arbeitet man mit .NET-Objekten in Python. Zwei Eigenheiten sind sofort sichtbar: Generische Methoden brauchen den Typ in eckigen statt in spitzen Klammern, und ist eine Methode am konkreten Objekt nicht sichtbar, hilft der Umweg über das Interface. Sammlungen dagegen verhalten sich unauffällig — was sich in .NET aufzählen lässt, lässt sich in Python ganz normal durchlaufen.

    An die laufende Instanz anhängen, ein benanntes Gerät greifen, sauber loslassen.
    anhaengen.pyPython
    """An ein laufendes TIA Portal anhängen und genau ein benanntes Gerät greifen."""
    
    import Siemens.Engineering as tia
    import Siemens.Engineering.HW.Features as hwf
    
    
    def plc_software(geraet):
        """Liefert die Steuerungssoftware eines Geräts oder None."""
        for teil in geraet.DeviceItems:
            # Der Umweg über das Interface hilft, wenn die Methode am konkreten
            # Objekt nicht sichtbar ist. Der Typ steht in eckigen Klammern.
            anbieter = tia.IEngineeringServiceProvider(teil)
            behaelter = anbieter.GetService[hwf.SoftwareContainer]()
            if behaelter is None:
                continue
            software = behaelter.Software
            if hasattr(software, "BlockGroup"):      # die Bedienoberflächen-Seite hat die nicht
                return software
        return None
    
    
    def geraet_nach_namen(projekt, gesucht):
        """Genau ein Treffer — oder Abbruch. Eine Position ist kein Selektor."""
        treffer = [g for g in projekt.Devices if g.Name == gesucht]
        if len(treffer) != 1:
            raise LookupError(f"{len(treffer)} Geräte mit dem Namen {gesucht!r}")
        return treffer[0]
    
    
    prozesse = list(tia.TiaPortal.GetProcesses())
    if not prozesse:
        raise SystemExit("Keine laufende TIA-Portal-Instanz gefunden.")
    
    with prozesse[0].Attach() as portal:        # ab pythonnet 3.1.0
        projekt = portal.Projects[0]
        geraet = geraet_nach_namen(projekt, "PLC_Linie_1")
        software = plc_software(geraet)
        if software is None:
            raise LookupError(f"{geraet.Name} führt keine Steuerungssoftware")
    
        for baustein in software.BlockGroup.Blocks:   # .NET-Sammlung, normal durchlaufbar
            print(baustein.Name)
        # BlockGroup.Blocks erfasst nur die oberste Gruppe. Untergruppen erreicht
        # man rekursiv über BlockGroup.Groups.
    
    # Hier endet die Sitzung — das TIA Portal bleibt offen. Das ist der
    # Unterschied zwischen Loslassen und Zumachen.

    Der Ausstieg aus dem with-Block trennt die Sitzung; das TIA Portal bleibt offen. Der with-Block funktioniert ab pythonnet 3.1.0 — davor gehört an dieselbe Stelle ein try/finally mit dem Aufruf zum Freigeben. Syntaktisch geprüft, nicht gegen ein reales TIA Portal ausgeführt.

  4. Jede Änderung einklammern

    Projekt

    Ein Lesezugriff darf abbrechen. Ein Schreibzugriff nicht: Bricht ein Lauf mitten in einer Schleife über zweihundert Bausteine ab, sind hundertdreißig im Projekt und der Rest nicht — und niemand weiß hinterher, welche.

    Drei Vorkehrungen gehören deshalb zusammen: eine Transaktion, die auf jedem Ausnahmepfad zurückgerollt wird; ein Archiv des Projekts, bevor überhaupt etwas importiert wird; und das bewusste Setzen der Importoption, statt sich auf die Voreinstellung zu verlassen.

    Import, Übersetzen und Rückrollen als eine Klammer.
    transaktion.pyPython
    """Änderungen einklammern — Ausschnitt, mit dem Siemens-Paket TIA Scripting Python.
    
    Vorausgesetzt sind ein geöffnetes `projekt`, die gewählte Steuerung `plc`, die
    übernommene Verbindung `portal`, `ts` als importiertes Paket und `quelle` als
    Wurzelverzeichnis der Importdateien.
    """
    
    # Zuerst das Netz, dann der Sprung: vor dem Import ein Archiv des Projekts
    # anlegen (projekt.archive).
    
    projekt.start_transaction(
        undo_text="Variablentabellen aus der I/O-Liste",
        dialog_text="Import läuft …",
    )
    try:
        plc.import_plc_tags(
            import_root_directory=quelle,
            # Den Parameter gibt es erst ab V1.4.3; unter älteren Ständen entfällt er.
            import_options=ts.Enums.GeneralImportOptions.Override,
        )
    
        ergebnis = plc.compile_software()
        fehler = ergebnis.get_errors()                   # ab V1.4.3 ein Ergebnisobjekt
        if fehler:
            raise RuntimeError(" | ".join(fehler))
    
        projekt.end_transaction(rollback=False)
    except Exception:
        projekt.end_transaction(rollback=True)           # auf JEDEM Ausnahmepfad
        raise
    finally:
        portal.detach()      # übernommene Instanz loslassen.
        # Die Schließen-Funktion würde dem Kollegen das TIA Portal zumachen.

    Zwei Brüche zwischen den Ständen des Siemens-Pakets: Das Übersetzen liefert ab V1.4.3 ein Ergebnisobjekt, davor einen Wahrheitswert, bei dem wahr für es-gab-Fehler stand — die alte Prüfung ist unter dem neuen Stand immer erfüllt. Auf der Bedienoberflächen-Seite gilt die umgekehrte Logik auch in V1.4.3 weiter. Und: Die dokumentierte Voreinstellung der Importoptionen überschreibt Gleichnamiges ohne Rückfrage.

    Eine Transaktion macht dabei nur das rückrollbar, was die Schnittstelle selbst zurücknehmen kann. Sie ersetzt das Archiv nicht.

  5. Den unbeaufsichtigten Lauf vorbereiten

    Betrieb

    Ein Skript, das neben dem geöffneten TIA Portal im Notizbuch läuft, ist etwas anderes als eines, das nachts durchläuft. Was den Unterschied ausmacht:

    • Rückfragen abfangen. Openness kennt Ereignisse für Meldungen und für Rückfragen. Ohne registrierte Behandlung bleibt ein unbeaufsichtigtes Skript an der ersten Rückfrage stehen, bis jemand am Rechner klickt.
    • Zeitgrenzen großzügig setzen. Siemens hält fest, dass der erste Openness-Aufruf länger dauert als jeder folgende. Eine Messung aus einem einzigen Aufruf führt in die Irre.
    • Optionspakete abgleichen. Jedes im Projekt verwendete Optionspaket und jede Hardware-Unterstützung muss auch auf dem ausführenden Rechner installiert sein — sonst scheitert schon das Öffnen des Projekts.
    • Den Ausfall sichtbar machen. Wenn der nächtliche Lauf ausbleibt, muss das jemand merken. Sonst fehlen im Nachweis Wochen, und niemand kann sagen, ab wann.

Die Fallen zwischen Python und Openness

Ein falscher Pfad meldet sich sofort und ist deshalb harmlos. Die folgenden Punkte sind unterschiedlich laut: Ein Teil bricht den Lauf beim ersten Versuch ab, ein anderer bleibt still — und wirkt trotzdem.

Fallstricke

Neun Punkte vor dem ersten Produktivlauf.

  • Der Enum-Wert None ist aus Python nicht direkt schreibbar

    Sowohl die Export- als auch die Importoptionen haben ein Element dieses Namens, und in Python ist der Name ein Schlüsselwort. Nötig ist der Umweg über den Namen als Zeichenkette.

  • Generische Methoden brauchen eckige Klammern

    Der Typ wird per Indexschreibweise gebunden, nicht in spitzen Klammern. Ist die Methode am konkreten Objekt nicht sichtbar, führt der Weg über den Umweg via Interface.

  • Zuweisungen an Werttypen laufen ins Leere

    Jeder Attribut- und Elementzugriff liefert eine verpackte Kopie. Der zu C# identisch aussehende Code ändert dann das Original nicht — ohne Fehlermeldung, ohne Spur.

  • Erweiterungsmethoden sind nicht als unterstützt beschrieben

    Wo die Schnittstelle darauf setzt, muss der definierende statische Typ direkt aufgerufen werden. Ein stiller Unterschied zu jedem C#-Beispiel, das man als Vorlage nimmt.

  • Ein Ereignisbehandler ohne Referenz verschwindet

    Wer den Behandler nicht in einer Variablen hält, verliert ihn irgendwann an die Speicherbereinigung. Der Fehler tritt sporadisch und spät auf — die schlechteste Kombination.

  • Alle Aufrufe gehören in einen einzigen Ausführungsstrang

    Für Openness ist kein Verhalten bei mehreren gleichzeitigen Strängen dokumentiert. Ein serieller Arbeitsstrang, der die Verbindung besitzt, ist die belastbare Annahme.

  • Eine Position in einer Sammlung ist kein Selektor

    Die Reihenfolge ist nicht zugesichert. Ein zweites Gerät im Projekt trifft still das falsche. Über den Namen filtern und bei null oder mehr als einem Treffer abbrechen.

  • Jeder Einzelzugriff kostet eine Runde über die Prozessgrenze

    Fünftausend Variablen einzeln umzubenennen dauert messbar länger als ein Export, eine Bearbeitung der XML-Datei und ein Import. Siemens führt für Massenänderungen selbst den zweiten Weg vor.

  • Eigenschaften gehen als Zeichenkette hinein

    Im Siemens-Paket nimmt das Setzen einer Eigenschaft immer Text entgegen — auch für Zahlen, Wahrheitswerte und Aufzählungen, Dezimalzahlen mit Punkt. Der Rückgabetyp der Gegenrichtung ist zwischen den Ständen widersprüchlich dokumentiert; aufrufender Code sollte beide Fälle abfangen.

Die Punkte eins bis fünf folgen aus Dokumentation und Quelltext von pythonnet, die Punkte sieben und acht aus der Openness-Dokumentation und den Siemens-Beispielen, Punkt neun aus den Unterlagen zum Siemens-Paket. Punkt sechs ist eine Annahme: Ein Verhalten bei mehreren gleichzeitigen Strängen ist nirgends dokumentiert, die Empfehlung stammt aus der Beschreibung eines Drittanbieters.

Die Wege, Python an das TIA Portal zu bringen

Die Brücke ist nicht der einzige Weg, und sie ist nicht immer der beste. Drei Bauformen stehen praktisch zur Wahl.

Bauformen

Dieselbe Aufgabe, drei sehr unterschiedliche Rechnungen.

Weg 1

pythonnet

Die Brücke im eigenen Prozess. Alles, was Openness kann, ist erreichbar — einschließlich dessen, was das Siemens-Paket nicht abdeckt: Geräte anlegen, Netze, der Vergleich zweier Projektstände.

Bezahlt wird mit der Laufzeitwahl, dem Auffinden der Assemblies und sämtlichen Übersetzungsfallen zwischen Python und .NET. Und mit einer Eigenschaft, die erst im Betrieb auffällt: Ein hängender Openness-Aufruf hängt im selben Prozess wie der Interpreter.

Volle Schnittstelle, volle Verantwortung

Weg 2

TIA Scripting Python

Das Angebot von Siemens selbst — ein Applikationsbeispiel, kein Bestandteil von Openness. Technisch eine übersetzte CPython-Erweiterung mit Adapter-Bibliotheken, also kein Aufsatz auf pythonnet: Sämtliche Brückenfallen entfallen.

Dafür ist das Wheel an genau drei CPython-Nebenversionen und an 64-Bit-Windows gebunden, und der Bezug läuft über einen Download mit Anmeldung statt über einen Paketverwalter.

Bezug nur über den Online-Support

Weg 3

Ein schlankes Programm in C#, von Python aufgerufen

Das Programm berührt Openness — mehr nicht: anhängen, exportieren oder importieren, übersetzen, fertig. Es gibt sein Ergebnis als JSON aus und wird als eigener Prozess mit Zeitgrenze gestartet. Python behält alles darum herum: Dateien, Tabellen, Vergleiche, Berichte, Versionsverwaltung.

Diese Bauform ist die einzige, bei der ein hängender Aufruf sich hart beenden lässt, ohne den Python-Prozess mitzunehmen. Und sie ist die einzige, die in der Freigabeliste ab V21 einen präzisen Eintrag bekommt — ein Programm, ein Eintrag, eine Prüfsumme. Auch die Assembly-Auflösung, die auf der Python-Seite Handarbeit bleibt, ist hier ein Paketverweis: Siemens veröffentlicht dafür ein eigenes NuGet-Paket, zuletzt in Version 2.0 vom 12.12.2025. Elegant ist die Bauform nicht. Belastbar schon.

Die Prozessgrenze als Sicherheitsnetz

Die Wahl entscheidet sich weniger an der Aufgabe als an der Frage, wer das Ergebnis später startet.

Daneben steht ein Weg, der die Brücke ganz vermeidet: IronPython läuft selbst auf der .NET-Laufzeit, .NET-Objekte sind dort keine übersetzten, sondern native Objekte. Der Stand 3.4.2 vom 20.12.2024 unter Apache-2.0 nennt als Ziele .NET Framework 4.6.2, .NET 6 und .NET 8 — für Openness kommt davon nur das erste in Frage. Bezahlt wird der Weg mit der Sprachbasis Python 3.4 und damit, dass C-Erweiterungen von CPython dort nicht laufen — kein pandas, kein lxml. Seit 12/2024 gab es kein Release. Für ein reines Openness-Skript ist der Weg gangbar; sobald Auswertung, Tabellen oder Versionsverwaltung dazukommen, verliert man den Grund, überhaupt Python zu nehmen.

Was auf PyPI steht — und was nicht

Die Frage nach dem Paket lässt sich kurz beantworten.

0

Pakete für TIA Portal Openness auf PyPI

Vollständiger Index, 26.08.2026

3

CPython-Nebenversionen, für die es das Siemens-Wheel gibt

Handbuch zu TIA Scripting Python V1.4.3, 06/2026

1

TIA-Version, die ein Prozess bedienen kann

Openness-Dokumentation V21

Die Prüfung lief gegen das vollständige Verzeichnis von PyPI, nicht gegen eine Suchmaske: kein Treffer auf „openness“, und die naheliegenden Namen liefern einen 404. Ein Kontrollabruf auf pythonnet lieferte im selben Durchgang eine gültige Antwort — die Schnittstelle war also erreichbar.

LandkarteWas es gibt, was es ist, und woher es kommt.
Name Was es ist Stand
pythonnet Die Brücke zwischen CPython und der .NET-Laufzeit. Nicht TIA-spezifisch. 3.1.0 · 23.05.2026 · MIT
clr-loader Lädt die Laufzeit für pythonnet, wird als Abhängigkeit mitinstalliert. Direkt anfassen muss man es nur für den Weg über die Konfigurationsdatei. 0.3.1 · 18.04.2026 · MIT
TIA Scripting Python Applikationsbeispiel von Siemens, übersetzte CPython-Erweiterung. Bezug ausschließlich über den Industry Online Support, Beitrag 109742322. Handbuch zu V1.4.3 · 06/2026
tia-openness-api-client Die bekannteste freie Abstraktion. Der Autor schreibt in der eigenen Projektbeschreibung, er könne den Code mangels TIA Portal nicht prüfen. Nicht auf PyPI. 0.1.0 · letzter Stand 08.01.2026 · MIT
IronPython Eine Python-Umsetzung, die selbst auf der .NET-Laufzeit läuft und deshalb ohne Brücke auskommt. Sprachbasis Python 3.4, keine C-Erweiterungen von CPython. Nicht auf PyPI. 3.4.2 · 20.12.2024 · Apache-2.0
simaticml-decoder Übersetzt exportierte Bausteine im SimaticML-Format nach lesbarem SCL. Berührt Openness nicht — und liegt als einziges TIA-nahes Paket tatsächlich auf PyPI. 0.2.3 · 20.07.2026 · MIT
pytia · simaticai · python-snap7 Namensfallen. Ein Interface-Server aus der Hirnforschung, das Edge-KI-Paket von Siemens, und Laufzeitkommunikation zur Steuerung. Keines berührt Openness

Versionsstände und Daten aus den Paket-Metadaten von PyPI, den GitHub-Schnittstellen und den Siemens-Unterlagen, alle abgerufen am 26.08.2026.

Der letzte Punkt ist mehr als eine Kuriosität. Er markiert die Trennlinie, an der die meisten Missverständnisse zu diesem Thema entstehen: Engineering heißt, das Projekt zu bearbeiten. Laufzeit heißt, Werte aus der laufenden Anlage zu lesen und zu schreiben. Für die zweite Aufgabe ist Openness das falsche Werkzeug; dort geht es um OPC UA und seine Grenzen oder um die klassische S7-Kommunikation.

Für die Bewertung eines Pakets folgt daraus eine einfache Regel: Sternezahl ist kein Reifegrad. Vor jeder Abhängigkeitsentscheidung gehören die Projektbeschreibung gelesen, der letzte Stand geprüft, die Lizenz angesehen — und die Frage beantwortet, ob es das Paket überhaupt an der Stelle gibt, an der man es beziehen will.

Wo Python an eine Grenze stößt

Nicht jede Aufgabe ist eine Frage des Geschmacks. Für einen Teil des Funktionsumfangs gibt es über Python schlicht keinen Weg — nicht, weil er umständlich wäre, sondern weil die Methoden fehlen.

Python, C#, oder gar keine Schnittstelle?

Die Reihenfolge zählt: Der erste zutreffende Fall ist die Antwort.

  • Wenn

    Geräte anlegen, Netze und Topologie projektieren

    Dann

    C#

    Das Siemens-Paket kennt kein Anlegen von Geräten, und Subnetze, Knoten, IO-Systeme und Portverschaltungen haben im Python-Objektmodell keine Entsprechung. Über Python bleibt allein der Weg über einen CAx-Import.

  • Wenn

    Zwei Projektstände offline miteinander vergleichen

    Dann

    C#

    Openness vergleicht dort gegen eine zweite Steuerung, gegen die Projekt- und die globale Bibliothek und gegen eine Master Copy. Aus Python heraus gibt es nur den Vergleich gegen die verbundene Steuerung.

  • Wenn

    Aus dem Skript wird ein Werkzeug, das andere unbeaufsichtigt starten

    Dann

    Ein C#-Programm, von Python aufgerufen

    Eindeutiger Eintrag in der Freigabeliste, Start mit Zeitgrenze, notfalls hartes Beenden — ohne dass die Python-Seite mitstirbt.

  • Wenn

    Einmaliger oder erkundender Eingriff, eine TIA-Version im Haus

    Dann

    pythonnet

    Der Weg steht in zwanzig Zeilen und braucht weder Visual Studio noch eine Übersetzungskette. Für den Autor selbst, nicht zum Ausrollen.

  • Wenn

    Prüfen, vergleichen, dokumentieren, erzeugen, berichten

    Dann

    Python auf den exportierten Dateien

    Ohne TIA-Lizenz, ohne Openness-Gruppe, ohne laufendes TIA Portal — und in einer Prüfstrecke wiederholbar.

Die beiden ersten Fälle sind keine Empfehlung, sondern eine Feststellung: Dort fehlen die Methoden, und kein Kniff auf der Python-Seite ändert daran etwas.

Es gibt noch einen sechsten Fall, der seltener genannt wird: alles, was in das TIA Portal hinein statt von außen darauf zugreift — Erweiterungen mit eigenen Menüeinträgen, Regelwerke für die Bildgenerierung, der modulare Applikationsaufbau. Das sind Bibliotheken, die das TIA Portal selbst lädt. Python kommt dort baulich nicht vor.

Der Weg, der die Frage entschärft

Bleibt die nüchternste Erkenntnis dieser Recherche — und sie steht am Ende, weil sie den Rest relativiert: Openness braucht man für den Ein- und den Ausgang. Alles dazwischen ist Dateiarbeit.

Architektur

Die Systemgrenze so schmal wie möglich halten.

Je weniger durch die Schnittstelle muss, desto weniger hängt an Laufzeit, Lizenz, Gruppenmitgliedschaft und Versionsstand.

TIA Portal

Export

Bausteine als SimaticML oder als externe Quelle, Variablentabellen als XML. Genau hier — und nur hier — berührt Openness das Projekt.

Dateien

SimaticML und SCL

Gewöhnliche Textdateien. Versionierbar, vergleichbar, lesbar — ohne TIA-Lizenz und ohne laufendes Portal.

Python

Prüfen, vergleichen, erzeugen

Namen prüfen, Adressen rechnen, Berichte bauen, zwei Stände semantisch vergleichen. Hier sitzt die Fachlogik, und hier ist Python stark.

TIA Portal

Import

Der Rückweg über dieselbe Schnittstelle. Für Massenänderungen um Größenordnungen schneller als der Einzelzugriff auf das Objektmodell.

Für Massenänderungen an Variablentabellen führt Siemens in den eigenen Beispielen genau diesen Weg vor — Export, Bearbeitung der XML-Datei, Import — und stellt ihn dem Einzelzugriff auf das Objektmodell gegenüber.

Wer so schneidet, macht die Wahl zwischen den drei Bauformen weitgehend gegenstandslos. Die Schnittstelle wird zu einer schmalen Schicht, die Daten über die Systemgrenze bewegt; die eigentliche Arbeit läuft auf Dateien und ist prüfbar, ohne dass jemand ein TIA Portal öffnet. Das ist zugleich der Grund, warum die nützlichsten Python-Werkzeuge in diesem Umfeld Openness gar nicht anfassen: Sie lesen exportierten SCL, vergleichen zwei Exportstände formatierungsblind oder übersetzen exportierte Bausteine in lesbaren Quelltext.

Und der Rest? Der Rest ist SPS-Programmierung. Was am Ende in der Steuerung läuft, entsteht weiterhin dort — Openness nimmt einem nur die Wiederholarbeit drumherum ab.

Fahrplan

Bevor ein Python-Skript das TIA Portal anfassen darf

Vier Voraussetzungen, die über Machbarkeit und Aufwand entscheiden — geklärt, bevor die erste Zeile Code entsteht.

  1. Windows-Gruppe und Sicherheitsabfrage klären

    Ohne Mitgliedschaft in der lokalen Gruppe für Openness endet jeder Verbindungsversuch in einer Sicherheitsausnahme. Nach dem Eintragen ist eine vollständige Ab- und Anmeldung nötig, und beim ersten Zugriff erscheint zusätzlich eine Abfrage im TIA Portal. Wer diese Abfrage dreimal ablehnt, bekommt dieselbe Ausnahme.

  2. Die TIA-Version des Zielrechners festhalten

    Ein Prozess bedient genau eine TIA-Version. Ab V21 heißt die Basis-Assembly anders und liegt an einer anderen Stelle als bis V20 — ein fest verdrahteter Pfad überlebt den Versionswechsel nicht.

  3. Den Interpreter festschreiben

    Die Brücke verlangt heute mindestens CPython 3.10, das Siemens-Paket gibt es nur für drei Nebenversionen und nur für 64 Bit. Welcher Interpreter das Skript ausführt, gehört in die Projektunterlagen, nicht in die Fehlersuche.

  4. Die Systemgrenze festlegen

    Alles, was auf exportierten Dateien möglich ist, braucht weder Openness noch eine TIA-Lizenz noch ein laufendes TIA Portal. Wo diese Grenze verläuft, entscheidet man vor dem Entwurf — danach ist es ein Umbau.

FAQ

Häufige Fragen.

Gibt es ein pip-Paket für TIA Portal Openness?

Nein. Eine Prüfung gegen das vollständige PyPI-Verzeichnis am 26.08.2026 ergab keinen Treffer; siemens-tia-scripting, tia-portal und tia-openness liefern dort einen 404. Der Weg führt entweder über pythonnet und eine selbst gebaute Brücke oder über das Siemens-Paket TIA Scripting Python, das ausschließlich als Download über den Industry Online Support zu beziehen ist.

Was ändert TIA Portal V21 an bestehenden Skripten?

Die monolithische Assembly entfällt. An ihre Stelle treten modulare Assemblies mit Siemens.Engineering.Base als Basis, sie liegen in einem Unterverzeichnis für die Ziel-Laufzeit, und der PublicKeyToken wechselt. Jedes Skript mit fest verdrahtetem Pfad findet unter V21 nichts mehr.

Weiterlesen

Alle Beiträge im Überblick

Kontakt

Stellen Sie Ihr Vorhaben vor.

Eine erste Einschätzung zu Ihrem Vorhaben ist kostenfrei und unverbindlich.

Zum Kontaktformular

Antwort innerhalb von zwei Werktagen