[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)))
|
||||
)
|
||||
|
||||
@@ -29,6 +29,23 @@ set "DXFM_RESULTS=%DXFMAKRO%\results"
|
||||
REM 2D/3D-Modus: Standard ist 3D (alle Module nutzen data\ils\3D\)
|
||||
set "DXFM_DIM=3D"
|
||||
|
||||
REM Python-Interpreter fuer die Export-Skripte (EXPORTCSV/EXPORTSIVAS).
|
||||
REM WICHTIG: BricsCAD erbt diese Umgebung, aktiviert aber kein venv. Ein blankes
|
||||
REM "python" trifft unter Windows 11 den WindowsApps-Platzhalter (kein echter
|
||||
REM Interpreter, bricht mit Exitcode 49 ab) - deshalb hier explizit setzen.
|
||||
set "DXFM_PYTHON="
|
||||
if exist "%DXFMAKRO%\.venv\Scripts\python.exe" (
|
||||
set "DXFM_PYTHON=%DXFMAKRO%\.venv\Scripts\python.exe"
|
||||
) else (
|
||||
for /f "delims=" %%P in ('py -c "import sys;print(sys.executable)" 2^>nul') do (
|
||||
if not defined DXFM_PYTHON set "DXFM_PYTHON=%%P"
|
||||
)
|
||||
)
|
||||
if not defined DXFM_PYTHON (
|
||||
echo HINWEIS: Kein Python gefunden - bin/install_py.bat ausfuehren, sonst
|
||||
echo liefern EXPORTCSV/EXPORTSIVAS keine CSV-Datei.
|
||||
)
|
||||
|
||||
set BRICSCAD="C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe"
|
||||
|
||||
if exist "C:\Program Files\Bricsys\BricsCAD V25 de_DE\bricscad.exe" (
|
||||
@@ -110,6 +127,7 @@ echo DXFM_DIM = %DXFM_DIM%
|
||||
echo DXFM_BLOCKS = %DXFM_BLOCKS%
|
||||
echo DXFM_OMNIFLO = %DXFM_OMNIFLO%
|
||||
echo DXFM_DIFFTOOL = %DXFM_DIFFTOOL%
|
||||
echo DXFM_PYTHON = %DXFM_PYTHON%
|
||||
echo ================================================================
|
||||
echo.
|
||||
|
||||
|
||||
@@ -42,6 +42,16 @@ pattern_separator= Separator_SP*, S-LP*
|
||||
pattern_scanner= Scanner*
|
||||
pattern_ks_subblocks= KS_EIN, KS_AUS, K1, K2, K3, K4
|
||||
|
||||
[python]
|
||||
# Interpreter fuer die Export-Skripte (lib/export_csv.py, lib/export_sivas.py).
|
||||
# Leer lassen = automatisch: DXFM_PYTHON (aus bin/setenv.bat) -> Projekt-venv
|
||||
# <DXFMAKRO>/.venv/Scripts/python.exe -> py.exe -> python (PATH).
|
||||
# Nur setzen, wenn ein bestimmter Interpreter erzwungen werden muss.
|
||||
# Wichtig: NICHT auf %LOCALAPPDATA%\Microsoft\WindowsApps\python.exe zeigen -
|
||||
# das ist nur der Microsoft-Store-Platzhalter (bricht mit Exitcode 49 ab und
|
||||
# der Export erzeugt dann keine CSV). Solche Pfade werden ignoriert.
|
||||
interpreter=
|
||||
|
||||
[Planquadrate]
|
||||
section=Planquadrate_AN
|
||||
|
||||
|
||||
@@ -500,6 +500,12 @@
|
||||
"exp-calling-python": "\n[%1] Rufe Python auf...",
|
||||
"exp-export-started": "\n[%1] Export gestartet: %2",
|
||||
"exp-python-not-found": "\n[%1] FEHLER: Python-Skript nicht gefunden: %2",
|
||||
"exp-python-exe": "\n[%1] Interpreter: %2",
|
||||
"exp-export-done": "\n[%1] Export fertig: %2",
|
||||
"exp-python-call-failed": "\n[%1] FEHLER: Python konnte nicht gestartet werden (WScript.Shell nicht verfuegbar).",
|
||||
"exp-python-error": "\n[%1] FEHLER: Python endete mit Exitcode %2. Log: %3",
|
||||
"exp-python-store-hint": "\n HINWEIS: Es wurde kein echter Python-Interpreter gefunden ('python' zeigt\n unter Windows 11 auf den WindowsApps-Platzhalter). Loesung: bin/install_py.bat\n ausfuehren (legt .venv an) und BricsCAD ueber bin/start_briscad.bat neu\n starten, oder in cfg/export.cfg unter [python] interpreter= den vollen Pfad\n zur python.exe setzen.",
|
||||
"exp-csv-missing": "\n[%1] FEHLER: Python meldete Erfolg, aber die CSV fehlt: %2. Log: %3",
|
||||
"exp-omni-no-inserts": "\n[OMNI_UPDATE] Keine INSERT-Bloecke in der Zeichnung.",
|
||||
"exp-omni-updated": "\n[OMNI_UPDATE] %1 Elemente aktualisiert (HOEHE, DREHUNG).",
|
||||
"id-new-assigned": "\n[ID] Neue ID zugewiesen: %1",
|
||||
|
||||
@@ -500,6 +500,12 @@
|
||||
"exp-calling-python": "\n[%1] Calling Python...",
|
||||
"exp-export-started": "\n[%1] Export started: %2",
|
||||
"exp-python-not-found": "\n[%1] ERROR: Python script not found: %2",
|
||||
"exp-python-exe": "\n[%1] Interpreter: %2",
|
||||
"exp-export-done": "\n[%1] Export finished: %2",
|
||||
"exp-python-call-failed": "\n[%1] ERROR: Could not start Python (WScript.Shell unavailable).",
|
||||
"exp-python-error": "\n[%1] ERROR: Python exited with code %2. Log: %3",
|
||||
"exp-python-store-hint": "\n NOTE: No real Python interpreter was found (on Windows 11 'python' points\n to the WindowsApps placeholder). Fix: run bin/install_py.bat (creates .venv)\n and restart BricsCAD via bin/start_briscad.bat, or set the full path to\n python.exe in cfg/export.cfg under [python] interpreter=.",
|
||||
"exp-csv-missing": "\n[%1] ERROR: Python reported success but the CSV is missing: %2. Log: %3",
|
||||
"exp-omni-no-inserts": "\n[OMNI_UPDATE] No INSERT blocks in the drawing.",
|
||||
"exp-omni-updated": "\n[OMNI_UPDATE] %1 elements updated (HEIGHT, ROTATION).",
|
||||
"id-new-assigned": "\n[ID] New ID assigned: %1",
|
||||
|
||||
Reference in New Issue
Block a user