[FIX] Python-Interpreter fuer Export robust ermitteln + Sprachtexte
Unter Windows 11 traf ein blankes "python" den WindowsApps-Platzhalter (kein echter Interpreter, Exitcode 49). Der Export schrieb die JSON, aber nie eine CSV - ohne jede Fehlermeldung, da "fire and forget" per startapp. - export:python-exe: Aufloesungsreihenfolge cfg/export.cfg [python] interpreter= -> DXFM_PYTHON -> Projekt-venv -> %SystemRoot%/py.exe -> "python"; WindowsApps-Platzhalter werden verworfen - export:run-python: synchroner Aufruf per WScript.Shell.Run, stdout/stderr nach DXFM_LOG/export_python.log, Exitcode-Auswertung - export:log-ausgeben: erste Logzeilen in die BricsCAD-Kommandozeile - setenv.bat setzt DXFM_PYTHON (venv oder py-Launcher) - cfg/export.cfg: neue Sektion [python] - lang/de_DE.json, lang/en_GB.json: neue Meldungstexte (exp-python-exe, exp-export-done, exp-python-error, exp-python-store-hint, exp-csv-missing, exp-python-call-failed) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+140
-7
@@ -68,6 +68,115 @@
|
||||
)
|
||||
|
||||
|
||||
;; ============================================================
|
||||
;; PYTHON-INTERPRETER ERMITTELN
|
||||
;; ============================================================
|
||||
;; BricsCAD erbt seine Umgebung von start_briscad.bat/setenv.bat - dort wird
|
||||
;; das Projekt-venv NICHT aktiviert. Ein blankes "python" trifft unter Windows
|
||||
;; 11 daher den WindowsApps-Platzhalter
|
||||
;; (%LOCALAPPDATA%\Microsoft\WindowsApps\python.exe), der kein Interpreter ist,
|
||||
;; sondern nur auf den Microsoft Store verweist und mit Exitcode 49 abbricht.
|
||||
;; Der Export schrieb dann zwar die JSON, aber nie eine CSV.
|
||||
;;
|
||||
;; Aufloesungsreihenfolge (erster Treffer gewinnt):
|
||||
;; 1. cfg/export.cfg [python] interpreter= (explizite Vorgabe)
|
||||
;; 2. Umgebungsvariable DXFM_PYTHON (von setenv.bat gesetzt)
|
||||
;; 3. <DXFMAKRO>/.venv/Scripts/python.exe (Projekt-venv, siehe install_py.bat)
|
||||
;; 4. "py" (Python-Launcher, C:\Windows\py.exe) - kein Store-Platzhalter
|
||||
;; 5. "python" (PATH) als letzter Ausweg
|
||||
(defun export:python-store-stub-p (pfad / p)
|
||||
(setq p (strcase (vl-string-translate "\\" "/" pfad)))
|
||||
(and (vl-string-search "/WINDOWSAPPS/" p) T)
|
||||
)
|
||||
|
||||
;; --- Kandidat pruefen: existierende Datei und kein Store-Platzhalter ---
|
||||
(defun export:python-kandidat-ok-p (pfad)
|
||||
(and pfad
|
||||
(/= pfad "")
|
||||
(findfile pfad)
|
||||
(not (export:python-store-stub-p pfad)))
|
||||
)
|
||||
|
||||
(defun export:python-exe ( / cfg-wert env-wert venv-pfad launcher-pfad)
|
||||
(cond
|
||||
;; 1. Explizite Vorgabe aus der Config
|
||||
((export:python-kandidat-ok-p
|
||||
(setq cfg-wert (export:cfg "python" "interpreter" "")))
|
||||
cfg-wert)
|
||||
;; 2. Umgebungsvariable
|
||||
((export:python-kandidat-ok-p (setq env-wert (getenv "DXFM_PYTHON")))
|
||||
env-wert)
|
||||
;; 3. Projekt-venv
|
||||
((export:python-kandidat-ok-p
|
||||
(setq venv-pfad (strcat (cond ((getenv "DXFMAKRO")) ("."))
|
||||
"/.venv/Scripts/python.exe")))
|
||||
venv-pfad)
|
||||
;; 4. Python-Launcher (liegt in C:\Windows, daher kein Store-Platzhalter).
|
||||
;; Voller Pfad statt nur "py.exe": findfile durchsucht die BricsCAD-
|
||||
;; Suchpfade, nicht zwangslaeufig den System-PATH.
|
||||
((export:python-kandidat-ok-p
|
||||
(setq launcher-pfad (strcat (cond ((getenv "SystemRoot")) ("C:/Windows"))
|
||||
"/py.exe")))
|
||||
launcher-pfad)
|
||||
;; 5. Letzter Ausweg - kann der Store-Platzhalter sein, deshalb wird der
|
||||
;; Exitcode nach dem Aufruf geprueft (siehe export:run-python).
|
||||
(t "python")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; --- Python-Skript synchron ausfuehren, Ausgabe in Logdatei ---
|
||||
;; Ersetzt das frueherer "fire and forget" (startapp "cmd" "/c ..."): das
|
||||
;; cmd-Fenster schloss sich sofort wieder, jede Python-Fehlermeldung (fehlender
|
||||
;; Interpreter, Traceback) war unsichtbar und der Befehl meldete trotzdem
|
||||
;; "Export gestartet". Jetzt wird ueber WScript.Shell.Run mit bWaitOnReturn=T
|
||||
;; gewartet, stdout/stderr nach DXFM_LOG/export_python.log umgeleitet und der
|
||||
;; Exitcode ausgewertet.
|
||||
;; Rueckgabe: Exitcode (0 = ok) oder nil, wenn der Aufruf selbst scheiterte.
|
||||
(defun export:run-python (py-exe py-skript args log-pfad / cmd sh rc code)
|
||||
;; Aeussere Anfuehrungszeichen um die gesamte /c-Zeile: sonst verschluckt
|
||||
;; cmd.exe die Quotes um den Interpreterpfad (Leerzeichen in "Program Files").
|
||||
(setq cmd (strcat "cmd.exe /c \"\"" py-exe "\""))
|
||||
(setq cmd (strcat cmd " \"" py-skript "\""))
|
||||
(foreach a args (setq cmd (strcat cmd " \"" a "\"")))
|
||||
(setq cmd (strcat cmd " > \"" log-pfad "\" 2>&1\""))
|
||||
;; Run(cmd, 0, T): 0 = kein Fenster, T = warten und Exitcode liefern.
|
||||
(setq rc
|
||||
(vl-catch-all-apply
|
||||
'(lambda ()
|
||||
(setq sh (vlax-create-object "WScript.Shell"))
|
||||
(setq code (vlax-invoke sh 'Run cmd 0 :vlax-true))
|
||||
(vlax-release-object sh)
|
||||
(setq sh nil)
|
||||
code)))
|
||||
(if (vl-catch-all-error-p rc)
|
||||
(progn
|
||||
(if sh (vl-catch-all-apply 'vlax-release-object (list sh)))
|
||||
nil)
|
||||
rc
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; --- Erste Zeilen der Python-Logdatei in die Kommandozeile spiegeln ---
|
||||
;; Damit steht die eigentliche Fehlerursache direkt in BricsCAD und nicht nur
|
||||
;; in der Logdatei. max-zeilen begrenzt die Ausgabe (Tracebacks koennen lang sein).
|
||||
(defun export:log-ausgeben (log-pfad max-zeilen / fh zeile n)
|
||||
(if (setq fh (open log-pfad "r"))
|
||||
(progn
|
||||
(setq n 0)
|
||||
(while (and (setq zeile (read-line fh)) (< n max-zeilen))
|
||||
(if (/= zeile "")
|
||||
(progn (princ (strcat "\n | " zeile)) (setq n (1+ n)))
|
||||
)
|
||||
)
|
||||
(close fh)
|
||||
)
|
||||
)
|
||||
(princ)
|
||||
)
|
||||
|
||||
|
||||
;; --- String fuer JSON escapen (Anfuehrungszeichen/Backslash) ---
|
||||
;; Konvertiert nicht-String-Werte (z.B. T, nil, Zahlen) defensiv in String.
|
||||
(defun csv:json-escape (s)
|
||||
@@ -458,7 +567,8 @@
|
||||
;; include-bbox = T -> Bounding-Box je Block ermitteln und mit exportieren
|
||||
;; (siehe csv:block-to-json); fuer EXPORTSIVAS nil.
|
||||
(defun csv:run-export (label py-name csv-name include-bbox / ss i ename fh out-pfad
|
||||
py-skript ergebnis-pfad cmd first-block count out-dir)
|
||||
py-skript ergebnis-pfad py-exe log-pfad rc first-block
|
||||
count out-dir)
|
||||
;; Vor dem Export: IDs aller Bloecke sicherstellen und Duplikate korrigieren
|
||||
(princ (ssg-textf "exp-check-ids" (list label)))
|
||||
(ssg-id-check-all)
|
||||
@@ -521,13 +631,36 @@
|
||||
(if (findfile py-skript)
|
||||
(progn
|
||||
(setq ergebnis-pfad (strcat out-dir "/" csv-name))
|
||||
(setq cmd (strcat "python \"" py-skript "\""
|
||||
" \"" out-pfad "\""
|
||||
" \"" (getenv "DXFM_DATA") "\""
|
||||
" \"" ergebnis-pfad "\""))
|
||||
(setq py-exe (export:python-exe))
|
||||
(setq log-pfad (strcat (cond ((getenv "DXFM_LOG")) (out-dir))
|
||||
"/export_python.log"))
|
||||
(princ (ssg-textf "exp-python-exe" (list label py-exe)))
|
||||
(princ (ssg-textf "exp-calling-python" (list label)))
|
||||
(startapp "cmd" (strcat "/c " cmd))
|
||||
(princ (ssg-textf "exp-export-started" (list label ergebnis-pfad)))
|
||||
;; Synchron ausfuehren und Exitcode auswerten - ein stiller
|
||||
;; Fehlschlag (z.B. WindowsApps-Platzhalter statt Interpreter)
|
||||
;; darf nicht mehr als "Export gestartet" durchgehen.
|
||||
(setq rc (export:run-python py-exe py-skript
|
||||
(list out-pfad (getenv "DXFM_DATA") ergebnis-pfad)
|
||||
log-pfad))
|
||||
(cond
|
||||
((null rc)
|
||||
(princ (ssg-textf "exp-python-call-failed" (list label))))
|
||||
((/= rc 0)
|
||||
(princ (ssg-textf "exp-python-error" (list label rc log-pfad)))
|
||||
(export:log-ausgeben log-pfad 12)
|
||||
;; Exitcode 49 (Store-Platzhalter direkt) bzw. 9009 (cmd.exe:
|
||||
;; "Befehl nicht gefunden") = kein brauchbarer Interpreter.
|
||||
;; Gezielter Hinweis, wie er korrekt gesetzt wird.
|
||||
(if (or (= rc 49) (= rc 9009)
|
||||
(export:python-store-stub-p py-exe))
|
||||
(princ (ssg-text "exp-python-store-hint"))
|
||||
))
|
||||
((not (findfile ergebnis-pfad))
|
||||
(princ (ssg-textf "exp-csv-missing" (list label ergebnis-pfad log-pfad)))
|
||||
(export:log-ausgeben log-pfad 12))
|
||||
(t
|
||||
(princ (ssg-textf "exp-export-done" (list label ergebnis-pfad))))
|
||||
)
|
||||
)
|
||||
(princ (ssg-textf "exp-python-not-found" (list label py-skript)))
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user