99 lines
3.6 KiB
Python
99 lines
3.6 KiB
Python
"""
|
||
geo_tools.config.settings
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
全局配置,通过 Pydantic BaseSettings 从环境变量 / .env 文件加载。
|
||
|
||
使用方式
|
||
--------
|
||
>>> from geo_tools.config.settings import settings
|
||
>>> print(settings.default_crs)
|
||
'EPSG:4326'
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import multiprocessing
|
||
from pathlib import Path
|
||
|
||
from pydantic import field_validator, model_validator
|
||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||
|
||
|
||
class GeoToolsSettings(BaseSettings):
|
||
"""全局运行时配置。
|
||
|
||
所有字段均可通过前缀为 ``GEO_TOOLS_`` 的环境变量覆盖,
|
||
或在项目根目录创建 ``.env`` 文件(参考 ``.env.example``)。
|
||
"""
|
||
|
||
model_config = SettingsConfigDict(
|
||
env_prefix="GEO_TOOLS_",
|
||
env_file=".env",
|
||
env_file_encoding="utf-8",
|
||
case_sensitive=False,
|
||
extra="ignore",
|
||
)
|
||
|
||
# ── 目录配置 ──────────────────────────────────────────────
|
||
output_dir: Path = Path("output")
|
||
"""处理结果输出目录(相对路径相对于当前工作目录)。"""
|
||
|
||
log_dir: Path = Path("logs")
|
||
"""日志文件目录。"""
|
||
|
||
# ── 坐标系配置 ────────────────────────────────────────────
|
||
default_crs: str = "EPSG:4326"
|
||
"""默认地理坐标系,使用 EPSG 代码字符串。
|
||
常见值:
|
||
- ``EPSG:4326`` — WGS84 经纬度
|
||
- ``EPSG:4490`` — CGCS2000 经纬度(中国国家标准)
|
||
- ``EPSG:3857`` — Web Mercator
|
||
"""
|
||
|
||
# ── 日志配置 ──────────────────────────────────────────────
|
||
log_level: str = "INFO"
|
||
"""日志等级:DEBUG / INFO / WARNING / ERROR / CRITICAL。"""
|
||
|
||
log_to_file: bool = True
|
||
"""是否同时将日志写出到文件。"""
|
||
|
||
# ── 性能配置 ──────────────────────────────────────────────
|
||
max_workers: int = 0
|
||
"""并行处理最大 CPU 核数,0 表示自动检测(使用 CPU 核数 - 1)。"""
|
||
|
||
# ── 校验器 ────────────────────────────────────────────────
|
||
|
||
@field_validator("log_level")
|
||
@classmethod
|
||
def validate_log_level(cls, v: str) -> str:
|
||
allowed = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
|
||
upper = v.upper()
|
||
if upper not in allowed:
|
||
raise ValueError(f"log_level 必须是 {allowed} 之一,收到:{v!r}")
|
||
return upper
|
||
|
||
@field_validator("default_crs")
|
||
@classmethod
|
||
def validate_crs(cls, v: str) -> str:
|
||
# 简单前缀校验,完整校验在 validators.py 中通过 pyproj 完成
|
||
v = v.strip()
|
||
if not v:
|
||
raise ValueError("default_crs 不能为空")
|
||
return v
|
||
|
||
@model_validator(mode="after")
|
||
def resolve_max_workers(self) -> "GeoToolsSettings":
|
||
if self.max_workers <= 0:
|
||
cpu_count = multiprocessing.cpu_count()
|
||
self.max_workers = max(1, cpu_count - 1)
|
||
return self
|
||
|
||
def ensure_dirs(self) -> None:
|
||
"""创建输出和日志目录(幂等)。"""
|
||
self.output_dir.mkdir(parents=True, exist_ok=True)
|
||
self.log_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
|
||
# 模块级单例,项目内统一引用
|
||
settings = GeoToolsSettings()
|