2 Commits

Author SHA1 Message Date
Claude
915b5c9f45 Diagnostic v2: log on module import, dual log paths, ship debug.bat
v0.3.3 wrapper only logged once it reached _main(). User reports CMD
window flashes shut and no log file created — meaning Python likely
never reached our code. Two fixes:

1. Move first log write to module top (before any project import) and
   write to BOTH the exe directory AND %LOCALAPPDATA%/sephiria_inv/.
   Either log existing proves Python booted; neither existing means
   PyInstaller bootloader itself failed.

2. Add run-debug.bat that runs the exe with stdout/stderr captured to
   sephiria_inv_console.log and pauses, so the window does not close
   before the user can read it.
2026-05-16 02:58:23 +09:00
Claude
a70499edfa Wrap startup in try/except with file log + Tk messagebox
--noconsole exes silently exit on import-time errors, so when v0.3.2
crashed during startup the user just saw nothing happen. This wrapper:
- Catches BaseException at module-import and main() level
- Writes traceback to %LOCALAPPDATA%/sephiria_inv/startup.log
- Pops a Tk messagebox-equivalent window with the traceback
- Falls back gracefully if Tk itself is unavailable

Also build with --console (no --noconsole) so prints/tracebacks are
visible in real time. Once we know what is failing we can re-enable
windowed mode.
2026-05-16 02:38:51 +09:00
2 changed files with 135 additions and 3 deletions

22
run-debug.bat Normal file
View File

@@ -0,0 +1,22 @@
@echo off
REM Run the exe with output captured. Window does not auto-close.
setlocal
cd /d "%~dp0"
echo Running sephiria_inv.exe ...
echo.
sephiria_inv.exe > sephiria_inv_console.log 2>&1
set EC=%errorlevel%
echo.
echo === sephiria_inv.exe exited with code %EC% ===
echo.
echo --- sephiria_inv_console.log ---
if exist sephiria_inv_console.log type sephiria_inv_console.log
echo --- end console.log ---
echo.
echo --- sephiria_inv_startup.log ---
if exist sephiria_inv_startup.log type sephiria_inv_startup.log
echo --- end startup.log ---
echo.
echo Press any key to close this window.
pause > nul
endlocal

114
run.py
View File

@@ -1,6 +1,116 @@
"""PyInstaller entry shim."""
"""PyInstaller entry shim with aggressive startup diagnostics.
Writes a log entry the moment this module is loaded (before any project
imports). Logs to two locations:
1. Next to the exe (sys.executable directory) -- usually the user's
Downloads folder; trivially findable.
2. %LOCALAPPDATA%/sephiria_inv/startup.log
Either log existing tells us Python started. Neither existing means the
PyInstaller bootloader died before Python ran (DLL/runtime issue).
"""
from __future__ import annotations
import os
import sys
import traceback
from datetime import datetime
def _candidate_log_paths():
paths = []
# 1. Next to the exe (most discoverable for the user)
try:
exe_dir = os.path.dirname(os.path.abspath(sys.executable))
if exe_dir:
paths.append(os.path.join(exe_dir, "sephiria_inv_startup.log"))
except Exception:
pass
# 2. LOCALAPPDATA / home
try:
base = os.environ.get("LOCALAPPDATA") or os.path.expanduser("~")
folder = os.path.join(base, "sephiria_inv")
os.makedirs(folder, exist_ok=True)
paths.append(os.path.join(folder, "startup.log"))
except Exception:
pass
return paths
def _write_log(msg: str) -> list:
written = []
stamp = datetime.now().isoformat()
for path in _candidate_log_paths():
try:
with open(path, "a", encoding="utf-8") as fh:
fh.write(f"\n=== {stamp} ===\n{msg}\n")
written.append(path)
except Exception:
pass
return written
def _env_dump() -> str:
lines = [
f"python: {sys.version}",
f"executable: {sys.executable}",
f"argv: {sys.argv}",
f"frozen: {getattr(sys, 'frozen', False)}",
f"_MEIPASS: {getattr(sys, '_MEIPASS', '<none>')}",
f"cwd: {os.getcwd()}",
f"PATH head: {os.environ.get('PATH', '')[:200]}",
f"LOCALAPPDATA: {os.environ.get('LOCALAPPDATA', '<none>')}",
]
return "\n".join(lines)
# === MODULE-IMPORT BREADCRUMB ===
# This runs the moment Python loads the entry script. If this never appears
# in either log, the PyInstaller bootloader failed before Python started.
_BOOT_LOGS = _write_log("BOOT: run.py loaded\n" + _env_dump())
def _show_error(title: str, body: str) -> None:
try:
import tkinter as tk
from tkinter import scrolledtext
root = tk.Tk()
root.title(title)
root.geometry("780x460")
txt = scrolledtext.ScrolledText(root, wrap="word")
txt.pack(fill="both", expand=True)
txt.insert("1.0", body)
tk.Button(root, text="Close", command=root.destroy).pack(pady=4)
root.mainloop()
except Exception:
pass
def _main() -> int:
try:
from sephiria_inv.__main__ import main
except BaseException:
tb = traceback.format_exc()
logs = _write_log("IMPORT FAIL\n" + tb + "\n--env--\n" + _env_dump())
_show_error(
"sephiria_inv: import failed",
f"Failed to import sephiria_inv.__main__\n\nLogs: {logs}\n\n{tb}",
)
return 11
try:
return int(main() or 0)
except SystemExit:
raise
except BaseException:
tb = traceback.format_exc()
logs = _write_log("RUNTIME FAIL\n" + tb)
_show_error(
"sephiria_inv: runtime error",
f"Crashed during main()\n\nLogs: {logs}\n\n{tb}",
)
return 12
if __name__ == "__main__":
raise SystemExit(main())
raise SystemExit(_main())