Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c17405a6b | ||
|
|
915b5c9f45 | ||
|
|
a70499edfa |
22
run-debug.bat
Normal file
22
run-debug.bat
Normal 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
|
||||||
116
run.py
116
run.py
@@ -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
|
||||||
|
|
||||||
from sephiria_inv.__main__ import main
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
raise SystemExit(main())
|
raise SystemExit(_main())
|
||||||
|
|||||||
@@ -409,11 +409,11 @@ class ScreenshotFrame(ttk.Frame):
|
|||||||
|
|
||||||
ctl = ttk.Frame(self)
|
ctl = ttk.Frame(self)
|
||||||
ctl.pack(fill="x")
|
ctl.pack(fill="x")
|
||||||
ttk.Button(ctl, text="🎮 게임 창 선택…", command=self._pick_window).pack(side="left")
|
ttk.Button(ctl, text="게임 창 선택…", command=self._pick_window).pack(side="left")
|
||||||
ttk.Button(ctl, text="🖥 전체 화면 캡처", command=self._capture_screen).pack(side="left", padx=4)
|
ttk.Button(ctl, text="전체 화면 캡처", command=self._capture_screen).pack(side="left", padx=4)
|
||||||
ttk.Button(ctl, text="📂 파일 열기…", command=self._open_file).pack(side="left", padx=4)
|
ttk.Button(ctl, text="파일 열기…", command=self._open_file).pack(side="left", padx=4)
|
||||||
ttk.Button(ctl, text="🔁 영역 재지정", command=self._reselect_bbox).pack(side="left", padx=4)
|
ttk.Button(ctl, text="영역 재지정", command=self._reselect_bbox).pack(side="left", padx=4)
|
||||||
ttk.Button(ctl, text="✅ 이 구성으로 계산", command=self._confirm).pack(side="right")
|
ttk.Button(ctl, text="이 구성으로 계산", command=self._confirm).pack(side="right")
|
||||||
|
|
||||||
self.status = ttk.Label(
|
self.status = ttk.Label(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in New Issue
Block a user