48 lines
1.9 KiB
Python
48 lines
1.9 KiB
Python
# PyInstaller frozen 환경과 일반 실행 환경 모두에서 올바른 기준 경로 반환
|
|
#
|
|
# 두 종류의 루트:
|
|
# BASE_PATH : 사용자가 보는 실제 폴더(쓰기 가능). 로그/변경된 설정/저장된 모델이 여기로.
|
|
# - dev 모드: __main__ 파일 위치 (= 프로젝트 루트)
|
|
# - EXE(--onefile) 모드: EXE가 놓인 폴더 (예: E:\ANT\dist)
|
|
# BUNDLE_PATH : 번들 안의 읽기 전용 자원 위치.
|
|
# - dev 모드: BASE_PATH 와 동일
|
|
# - EXE 모드: PyInstaller 임시 추출 폴더 (sys._MEIPASS)
|
|
import os
|
|
import sys
|
|
|
|
|
|
def get_base_path() -> str:
|
|
"""사용자 데이터 위치(읽기/쓰기)."""
|
|
if getattr(sys, "frozen", False):
|
|
return os.path.dirname(os.path.abspath(sys.executable))
|
|
main_mod = sys.modules.get("__main__")
|
|
main_file = getattr(main_mod, "__file__", None)
|
|
if main_file:
|
|
return os.path.dirname(os.path.abspath(main_file))
|
|
# path_helper.py lives in utils/ — go up one level to reach the project root
|
|
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
def get_bundle_path() -> str:
|
|
"""번들된 자원 위치(읽기 전용). EXE에선 _MEIPASS, dev에선 BASE_PATH."""
|
|
return getattr(sys, "_MEIPASS", BASE_PATH)
|
|
|
|
|
|
BASE_PATH = get_base_path()
|
|
BUNDLE_PATH = get_bundle_path()
|
|
|
|
|
|
def get_path(*paths) -> str:
|
|
"""경로 결합. BASE_PATH 기준 우선, 거기 없으면 BUNDLE_PATH 폴백.
|
|
파일이 양쪽에 다 없으면 BASE_PATH 기준 경로 반환(신규 생성 시 사용자 영역에 만들도록)."""
|
|
if not paths:
|
|
return BASE_PATH
|
|
primary = os.path.join(BASE_PATH, *paths)
|
|
if os.path.exists(primary):
|
|
return primary
|
|
if BUNDLE_PATH and BUNDLE_PATH != BASE_PATH:
|
|
fallback = os.path.join(BUNDLE_PATH, *paths)
|
|
if os.path.exists(fallback):
|
|
return fallback
|
|
return primary
|