feat: add path helper functions to file_service
- get_app_dir(): project root in dev, exe dir in PyInstaller bundle - get_resource_path/get_config_path: paths under app dir - get_log_dir/get_output_dir: auto-create and return logs/ and output/ - Refactor log_service to use get_log_dir() instead of own __file__ calc Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,51 @@
|
|||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
SUPPORTED_IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp"}
|
SUPPORTED_IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp"}
|
||||||
|
|
||||||
|
|
||||||
def is_supported_image(path):
|
def is_supported_image(path):
|
||||||
return path.suffix.lower() in SUPPORTED_IMAGE_EXTENSIONS
|
return path.suffix.lower() in SUPPORTED_IMAGE_EXTENSIONS
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Path helpers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_app_dir():
|
||||||
|
"""Return the application root directory as a Path.
|
||||||
|
|
||||||
|
PyInstaller onedir: directory that contains the .exe.
|
||||||
|
Development: project root (three levels above this file:
|
||||||
|
src/services/file_service.py -> src/services -> src -> project root).
|
||||||
|
"""
|
||||||
|
if getattr(sys, "frozen", False):
|
||||||
|
return Path(sys.executable).resolve().parent
|
||||||
|
return Path(__file__).resolve().parent.parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
def get_resource_path(relative_path):
|
||||||
|
"""Return absolute Path for a file under <app_dir>/resources/."""
|
||||||
|
return get_app_dir() / "resources" / relative_path
|
||||||
|
|
||||||
|
|
||||||
|
def get_config_path(relative_path):
|
||||||
|
"""Return absolute Path for a file under <app_dir>/config/."""
|
||||||
|
return get_app_dir() / "config" / relative_path
|
||||||
|
|
||||||
|
|
||||||
|
def get_log_dir():
|
||||||
|
"""Return <app_dir>/logs/ as a Path, creating the directory if absent."""
|
||||||
|
d = get_app_dir() / "logs"
|
||||||
|
d.mkdir(exist_ok=True)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def get_output_dir():
|
||||||
|
"""Return <app_dir>/output/ as a Path, creating the directory if absent."""
|
||||||
|
d = get_app_dir() / "output"
|
||||||
|
d.mkdir(exist_ok=True)
|
||||||
|
return d
|
||||||
|
|||||||
+29
-18
@@ -6,28 +6,32 @@ from datetime import datetime
|
|||||||
def setup_logging(log_dir=None):
|
def setup_logging(log_dir=None):
|
||||||
"""Initialize file + console logging. Call once at application startup.
|
"""Initialize file + console logging. Call once at application startup.
|
||||||
|
|
||||||
log_dir: absolute path to log directory. Defaults to <project_root>/logs/.
|
log_dir: str or Path to log directory. Defaults to <app_dir>/logs/ via
|
||||||
If the directory cannot be created, falls back to console-only logging.
|
file_service.get_log_dir(). Falls back to console-only if the
|
||||||
|
directory cannot be created.
|
||||||
"""
|
"""
|
||||||
if log_dir is None:
|
if log_dir is None:
|
||||||
# src/services/log_service.py -> src/services -> src -> project root
|
try:
|
||||||
_here = os.path.dirname(os.path.abspath(__file__))
|
from services.file_service import get_log_dir
|
||||||
log_dir = os.path.join(os.path.dirname(os.path.dirname(_here)), "logs")
|
log_dir = get_log_dir()
|
||||||
|
except OSError as exc:
|
||||||
try:
|
_setup_console_only()
|
||||||
os.makedirs(log_dir, exist_ok=True)
|
logging.getLogger(__name__).warning(
|
||||||
except OSError as exc:
|
"Cannot create log directory: %s. Falling back to console only.", exc
|
||||||
logging.basicConfig(
|
)
|
||||||
level=logging.INFO,
|
return
|
||||||
format="%(asctime)s %(name)s %(levelname)s %(message)s",
|
else:
|
||||||
)
|
try:
|
||||||
logging.getLogger(__name__).warning(
|
os.makedirs(str(log_dir), exist_ok=True)
|
||||||
"Cannot create log directory %s: %s. Falling back to console only.", log_dir, exc
|
except OSError as exc:
|
||||||
)
|
_setup_console_only()
|
||||||
return
|
logging.getLogger(__name__).warning(
|
||||||
|
"Cannot create log directory %s: %s. Falling back to console only.", log_dir, exc
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
log_file = os.path.join(log_dir, "app_{}.log".format(timestamp))
|
log_file = os.path.join(str(log_dir), "app_{}.log".format(timestamp))
|
||||||
|
|
||||||
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
|
formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
|
||||||
|
|
||||||
@@ -43,3 +47,10 @@ def setup_logging(log_dir=None):
|
|||||||
root.addHandler(sh)
|
root.addHandler(sh)
|
||||||
|
|
||||||
logging.getLogger(__name__).info("Logging initialized. Log file: %s", log_file)
|
logging.getLogger(__name__).info("Logging initialized. Log file: %s", log_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_console_only():
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s %(name)s %(levelname)s %(message)s",
|
||||||
|
)
|
||||||
|
|||||||
@@ -87,18 +87,18 @@
|
|||||||
|
|
||||||
任务:
|
任务:
|
||||||
|
|
||||||
- [ ] 在 `src/services/file_service.py` 中新增路径辅助函数(不单独建模块)
|
- [x] 在 `src/services/file_service.py` 中新增路径辅助函数(不单独建模块)
|
||||||
- [ ] 实现 `get_app_dir()`:返回程序根目录,兼容开发环境和 PyInstaller 打包环境
|
- [x] 实现 `get_app_dir()`:返回程序根目录,兼容开发环境和 PyInstaller 打包环境
|
||||||
- [ ] 实现 `get_resource_path(relative_path)`:返回资源文件绝对路径
|
- [x] 实现 `get_resource_path(relative_path)`:返回资源文件绝对路径
|
||||||
- [ ] 实现 `get_config_path(relative_path)`:返回配置文件绝对路径
|
- [x] 实现 `get_config_path(relative_path)`:返回配置文件绝对路径
|
||||||
- [ ] 实现 `get_log_dir()`:返回日志目录路径
|
- [x] 实现 `get_log_dir()`:返回日志目录路径
|
||||||
- [ ] 实现 `get_output_dir()`:返回默认输出目录路径
|
- [x] 实现 `get_output_dir()`:返回默认输出目录路径
|
||||||
- [ ] 保证 Windows 中文路径可用
|
- [x] 保证 Windows 中文路径可用
|
||||||
|
|
||||||
验收:
|
验收:
|
||||||
|
|
||||||
- [ ] 路径函数不使用开发机绝对路径
|
- [x] 路径函数不使用开发机绝对路径
|
||||||
- [ ] 程序目录下缺少 `logs/` 或 `output/` 时可自动创建
|
- [x] 程序目录下缺少 `logs/` 或 `output/` 时可自动创建
|
||||||
|
|
||||||
### 1.3 配置服务
|
### 1.3 配置服务
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user