Support Forum

[Frage] PP-Interactor in Kombination mit Python-Formelattribut am Bauteil

Schlagworte:
  • PythonParts
  • |Interactor
  • Python-Formelattribute
  • Allplan
  • Python

Hallo zusammen,

bei der Umsetzung eines Python Parts (PP) mit Interactor bin ich auf ein für mich unerklärliches Phänomen gestoßen. Vielleicht könnt ihr mit helfen bzw. könnt mir erklären was im Hintergrund passiert.

Ausgangslage ist ein PP mit Interactor. Ich habe Testweise mal einfach das PP SelectObjectsWith3DGeometry aus den von Allplan mitgelieferten PParts gewählt (Ordner: …\Etc\Examples\PythonParts\ModelObjectExamples\SelectionExamples). Mit dem PP kann man 3D-Elemente auswählen. Diese werden dann in einer Liste in der PP-Palette angezeigt.

In meiner Testumgebung habe ich mir zwei Bauteile modelliert und an beide Bauteile die Attribute Kurztext und Langtext angehängt. Zusätzlich habe ich mir zwei benutzerdefinierte Formelattribute erstellt (siehe Bild 1). Das Python-Formelattribut aus Bild 1 greift auf eine Funktion aus der Datei functions.py (Ordner: …\Std\Scripts) zu. Die Funktion habe ich (Python)-identisch zum "Allplan"-Formelattribut umgesetzt (siehe Bild 2). Danach jeweils ein Formelattribut an eine der Stützen angehängt.

Anschließen habe ich beide Bauteile einmal mit dem o.g. PP ausgewählt.

Wenn man jetzt das Bauteil mit dem Python-Formelattribut aufruft und dabei die Eigenschaften-Palette auf hat wird das PP Script SelectObjectsWith3DGeometry 2x ausgeführt/geladen (siehe Bild 3). Bei einem Element nicht schlimm aber bei 10 Elementen -> 20x Load SelectObjectsWith3DGeometry.py (sehr schlechte Performance). Dies gilt dann auch wenn man das Bauteil nur kopiert also nicht mit dem Interactor des PP anrührt. Wenn man Allplan schließt und neu öffnet ist erstmal der Spuck vorbei, aber sobald man das PP wieder aufruft, fängt das Spiel von vorne an.

Wenn man eines der Attribute (Kurztext oder Langtext) modifiziert wird das PP ebenfalls geladen.

Verwendet man das o.g. Python-Formelattribut in einer Formel-Zelle einer Legende und verwendet ebenfalls eine Funktion aus functions.py kommt die Meldung das Python nicht gestartet werden konnte (siehe Bild 4).

Kann man dieses aufrufen bzw. das laden des PythonPart – Skiptes beim auswählen der Bauteile verhindern werden? Und vor allem, wo ist da die Verbindung zwischen einem PythonPart und einem Python-Formelattribut, welche auf die functions.py – Datei zurückgreift?

Als Workaround werde ich jetzt erstmal versuchen auf Python-Formelattribute an Bauteilen zu verzichten. Aber gut wäre es schon wenn es hierzu eine Lösung gäbe…

Version: Allplan 2024

PS: Die <ReadLastInput>False</ReadLastInput> Zeile in der .pyp Datei des PP habe ich testweise auf False gestellt . Hat leider nichts geändert, dies speichert auch nur die Benutzereingaben die in der Palette gemacht werden oder?

Anhänge (3)

Typ: image/png
48-mal heruntergeladen
Größe: 247,26 KiB
Typ: image/png
28-mal heruntergeladen
Größe: 4,83 KiB
Typ: image/png
44-mal heruntergeladen
Größe: 35,35 KiB

Hilfreichste Antwort anzeigen Hilfreichste Antwort verbergen

Nochmal zu Flaschenhals: das Reloading vom zuletzt ausgeführtem PythonPart ist tatsächlich dem reloader geschuldet. Als workaround würde ich vorschlagen, den auszuschalten:

  • Folgender Order öffnen: Prg\Python\lib\site-packages\
  • die darin enthaltene Datei reloader.py umbenennen (z.B. _reloader.py)

Natürlich, ist es nur ein Workaround. Voraussichtlich werden wir den Reloader komplett aus Allplan entfernen, denn es macht noch mehr Probleme (z.B. mit manchen site-packages wie numpy) und ist für nicht-Entwickler eigentlich überflüssig. Seine Aufgabe ist, wie der Name schon sagt, den Skript vor jeder Ausführung nochmal zu laden. Um, wenn man einen Python Skript erstellt, nicht nach jeder Änderung Allplan neu starten zu müssen. Wenn der Skript aber fertig ist, kann man darauf verzichten.

Viele grüße,
Bart

Scheinbar wird derselbe Python-Interpreter für die Python-Formel als auch für das PythonPart benutzt. Dabei wird scheinbar die Python-Umgebung nicht korrekt bereinigt, nachdem man das PythonPart ausgeführt hat. Sprich: Die Klassen und Funktionen SelectObjectsWith3DGeometry.py sind noch irgendwie im __main__-Module bzw. dessen Namespace (__main__.attr("__dict__")) vorhanden, und werden bei jedem Interpreter-Aufruf (für die Python-Formel) wieder neu geladen. (ggf. mit Python function reload())
Und das passiert eben jedesmal, wenn das Formel-Attribut berechnet und angezeigt werden muss, also zumindest bei der Selektion mit offener Eigenschaftspalette. Beim "bloßen" Kopieren sollte die Python-Formel und damit der Python-Interpreter eigentlich nicht ausgeführt werden!

Besser wäre es, für jeden Interactor und für jede Formel ein neues, frisches __main__.Module samt Namespace zu verwenden. Sonst könnte das irgendwie ein Flaschenhals werden, wenn man viele PythonParts während einer Allplan-Sitzung benutzt.

Scheinbar wird nur bei einem Neustart von Allplan dieses __main__.Module samt Namespace neu initialisiert!

Danke für die Rückmeldung.

Das im Hintergrund irgendetwas vorhanden bleibt habe ich mir auch schon irgendwie gedacht, anders konnte ich mir das auch nicht erklären.

Richtig, beim bloßen Kopieren der Bauteile kommt das wiederholte laden des PP nicht vor. Ich meinte mit "Kopieren" auch nur wenn ich das Bauteil mit dem Python-Formelattribut kopiere und dann die Kopie mit dem Eigenschaften-Fenster offen anwähle. Das erneute Laden kommt bei allen Objekten vor die ein Python-Formelattribut haben.

Zum Flaschenhals: Wenn man neben den oben genannten PP dann auch noch ein weiteres Interactor-PP ausführt z.B. GetObjectByAttibuteValue und ein Attribut im PP auswählt kommt ebenfalls die Meldung die ich in meiner ersten Nachricht mit Bild 4 meinte.

Das mit dem neuen __main__.Modul für jeden Interactor und jede Formel klingt nach etwas, was vermutlich dann in der API-Schnittstelle umgesetzt werden könnte/müsste. Also eher was für Allplan... @Allplan soll ich ein Issue aufmachen? Link

Gäbe es denn die theoretische Möglichkeit, dass man eventuell in der Interactor - Funktion "on_cancel_function" die Überbleibsel im Hintergund beim beenden des PP entfernen könnte?

Anhänge (1)

Typ: image/png
28-mal heruntergeladen
Größe: 8,78 KiB

Hallo zusammen,

Vielen dank euch beiden für den Feedback. Offensichtlich läuft im Hintergrund etwas verkeht. Ich konnte das problem bei mir reproduzieren und tatsächlich wird der Python modul für das zuletzt gestartete PythonPart zweimal geladen. Wir werden uns das anschauen.

Grüße,
Bart

Bild 4 beweist, dass es scheinbar nur einen Python-Interpreter gibt.
Und da der schon beim Interactor gestartet ist, kann er für die Python-Formel nicht nochmal
gestartet werden. Daher die Fehlermeldung.

Allplan müßte das wirklich trennen: einen Interpreter für die PythonParts (mit/ohne Interactor),
und einen anderen für die Python-Formeln!

Das ist tatsächlich der Fall, es gibt nur einen Python interpreter. Zwei Python interpreter ist eine mögliche Lösung. Andere könnte z.B. das deaktivieren von reloader sein. Der ist nämlich immer aktiv, gebraucht wird er aber nur beim entwickeln, um nicht bei jeder Änderung Allplan neu starten zu müssen. Im täglichen gebrauch ist er nicht nötig, da kaum jemand die Skripte täglich ändert.

Nochmal zu Flaschenhals: das Reloading vom zuletzt ausgeführtem PythonPart ist tatsächlich dem reloader geschuldet. Als workaround würde ich vorschlagen, den auszuschalten:

  • Folgender Order öffnen: Prg\Python\lib\site-packages\
  • die darin enthaltene Datei reloader.py umbenennen (z.B. _reloader.py)

Natürlich, ist es nur ein Workaround. Voraussichtlich werden wir den Reloader komplett aus Allplan entfernen, denn es macht noch mehr Probleme (z.B. mit manchen site-packages wie numpy) und ist für nicht-Entwickler eigentlich überflüssig. Seine Aufgabe ist, wie der Name schon sagt, den Skript vor jeder Ausführung nochmal zu laden. Um, wenn man einen Python Skript erstellt, nicht nach jeder Änderung Allplan neu starten zu müssen. Wenn der Skript aber fertig ist, kann man darauf verzichten.

Viele grüße,
Bart

Danke für die Recherche.

Habe dein Workaround mal ausprobiert. Zumindest ist es dann mit der Performace nicht mehr so schlimm wenn man Bauteile auswählt die auf ein Python-Formelattribut zurückgreifen.
Die Meldung (Bild 4) das Python nicht gestartet werden kann (weil wahrscheinlich der Interpreter schon genutzt wird) erscheint aber trotzdem sobald ein zweites PythonPart gestartet wird. Die Meldung muss dann bis Programmende unterdrückt werden, sonst gibt es eine Endlosschleife...

Ich werde aber vermutlich trotzdem von Python-Attributformeln auf VSscipt-Formel für die Attribute switchen müssen. Da wenn ich in einer Allplan-Legende das Python-Formelattribut nochmal in einer Python-Zellenformel benutze vor dem gleichen Hindernis stehe .