Nja, wir hatten ursprünglich Python als "Embedded" mitgeliefert (nur nannte es damals noch niemand so).
Also als ZIP runtergeladen und die EXE (inkl.
DLL und Co.) als Unterverzeichnis beim Programm.
Das aktuelle Script wurde als .py-Datei auf die Festplatte geschieben,
dann die Python.exe gestartet, die Datei als Parameter übergeben und dann via ShellExecute/CreateProzess die Ausgabe in eine Datei umgeleitet.
Später der Ausgabestream direkt im CreateProzess übergeben und die Ausgabe in ein unsichtbares TMemo, was dann weiterverwendet wurde und sich beim Dedbuggen anzeigen ließ.
Zuletzt dann Python4Delphi eingeführt, wo das Script als Stream/String im Programm bleibt und auch die Ausgabe in einem Stream/String landet.
Zusätzlich noch ein paar Variablen und Delphi-Funktionen reingegeben, welche sich im Python nutzen lassen.
Auch lässt sich hier intern schöner die Fehlerbehandlung machen. Also vorher ein SyntaxCheck und bei einem Fehler erweiterte Fehlerinfos von der
DLL abrufen.
Dann ging es darum auch Fremdcode zu nutzen (bisher vorwiegend nur selbsterstellte PythonScripte)
und da sind wir dann zu PIP übergegangen, da es manuell schnell umständlich wird, mit all den Abhängigkeiten.
Als allerletztes dann noch die Ausgabe im Python auf
Unicode umgestellt, denn rein ging es schon als
Unicode, aber die Ausgabe sollte eigentlich UTF-8 sein (war aber
ANSI).
Bei der EXE war es so, dass die Python-Instanz immer neu ist
und ein Script niemals Auswirkungen auf nachfolgende Scripte hat.
-> Wurde z.B. in einem Script vergessen eine Variable zu initialisieren,
dann was diese Variable in der EXE immer leer,
aber nun in der
DLL hatte sie den Wert einer vorhergehenden Ausführung, was das Verhalten manchmal plötzlich veränderte.
Da wir damals es nicht geschafft hatten, die Instanz (Variablen und geladene Module) zurückzusetzen,
wird aktuell nach jeder Ausführung eines Scriptes die Instanz freigegeben und die Python-
DLL entladen.
Beim nächsten Laden war somit alles wieder neu/leer.
Das lief bisher gut und auch flott.
Dann versuchte jemand PySide2 und shiboken2 nutzen zu wollen.
Ersteres lädt selbst DLLs und entlädt sich nicht mehr. (Entwickler für Scriptsprachen sind einfach nur faule Schlampen ... siehe meine Signaur)
Diese DLLs haben auch noch eine Referenz auf die python3.dll, welche wiederrum die python38.dll (welche wir geladen haben und nutzen) referenziert, womit sich alles gegenseitig im
RAM festkrallt, nachdem wir unsere Referenz auf die python38.dll freigaben und dachten es wäre nun entladen.
Erstmal hatte hier Python4Delphi einen Bug, so dass es in der Finalisazion beim Entladen der einen
DLL einen
Exception gibt (das ist OK), aber nachfolgend anderes vergessen wird zu finalisieren und freizugeben. (try-finally vergessen)
Dennoch bleibt irgendwas im
RAM (auch wenn manuell alle DLLs entladen werden), was dann beim nächsten Laden und der Initialisation zu einer
Exception führt und es nicht mehr erlaubt weitere Scripte auszuführen (python4delphi bricht beim Laden und starten des Scripts ab).
Ja, ich kann manuell diese DLLs in der richigen Reihenfolge entladen (testweise für PySide2 gemacht),
aber da der Code universell sein muß, weil ich garnicht weiß, welche Komponenten/PythonModule zukünftig genuzt werden.
Hier hab ich mich nun mühevoll in Windows "gehackt", um an die LadeListen der DLLs zu kommen (inkl. Rehenfolge/Uhrzeit und dem Grund des Ladens, also manuell oder durch automatische Abhängigkeit)
Das wird nun genutzt die FremdDLLs zu finden und zu entladen.
Aber wie gesagt, irgendwo bleibt noch was zurück und knallt nachfolgend. Das hatte ich noch nicht gefunden, drum hängt das Projekt hier erstmal, da Anderes wichtiger.