diff --git a/app/core/logging.py b/app/core/logging.py index 56b856b..3e63ea5 100644 --- a/app/core/logging.py +++ b/app/core/logging.py @@ -87,5 +87,9 @@ def setup_logging(debug: bool = False) -> None: # 第三方库降噪 logging.getLogger("httpx").setLevel(logging.WARNING) logging.getLogger("httpcore").setLevel(logging.WARNING) + # uvicorn --reload 的文件监视器: DEBUG 下会把每次"检测到变更"打出来。我们的 root 文件 + # handler 又把这行写回 logs/app-server.log → watchfiles 再次检测 → 自我喂食死循环。 + # 降到 WARNING 同时消除噪音和这个回环(真正的 .py 热重载不受影响)。 + logging.getLogger("watchfiles").setLevel(logging.WARNING) _CONFIGURED = True diff --git a/run.bat b/run.bat index 1a83f75..379b096 100644 --- a/run.bat +++ b/run.bat @@ -17,6 +17,12 @@ REM avoids CRLF/encoding fights every time someone bash-runs the .sh on Win. cd /d "%~dp0" +REM Prefer the project virtualenv (.venv) so we never inherit a wrong +REM global/conda interpreter. FastAPI<0.115 on Pydantic 2.12 crashes at import +REM with "'FieldInfo' object has no attribute 'in_'". Falls back to PATH python. +set "PY=python" +if exist "%~dp0.venv\Scripts\python.exe" set "PY=%~dp0.venv\Scripts\python.exe" + if not exist .env ( echo [X] Missing .env. Run: copy .env.example .env and fill JWT_SECRET_KEY ^(plus MT_CPS_* if you test Meituan^) exit /b 1 @@ -25,11 +31,11 @@ if not exist .env ( if not exist data mkdir data REM Build/upgrade SQLite schema (idempotent; no-op if already at head) -call alembic upgrade head +call "%PY%" -m alembic upgrade head if errorlevel 1 ( echo [X] alembic upgrade head failed exit /b %errorlevel% ) REM Long-running foreground process. Ctrl+C to stop. -uvicorn app.main:app --host 0.0.0.0 --port 8770 --reload +"%PY%" -m uvicorn app.main:app --host 0.0.0.0 --port 8770 --reload diff --git a/run.sh b/run.sh index bc00fe8..d7695e9 100755 --- a/run.sh +++ b/run.sh @@ -7,12 +7,20 @@ set -e cd "$(dirname "$0")" +# 优先用项目 venv 的解释器,避免误用全局/conda 里不兼容的 FastAPI/Pydantic +# (FastAPI<0.115 撞 Pydantic 2.12 会在导入期崩 'FieldInfo' has no attribute 'in_')。 +PY=python +[ -x .venv/bin/python ] && PY=.venv/bin/python +[ -x .venv/Scripts/python.exe ] && PY=.venv/Scripts/python.exe + if [ ! -f .env ]; then echo "❌ 缺 .env:先 cp .env.example .env 并填值(至少 JWT_SECRET_KEY;测美团再填 MT_CPS_*)" exit 1 fi mkdir -p data # sqlite 文件所在目录 -alembic upgrade head # 确保表已建(幂等,已是最新则 no-op) +"$PY" -m alembic upgrade head # 确保表已建(幂等,已是最新则 no-op) -exec uvicorn app.main:app --host 0.0.0.0 --port 8770 --reload +# --reload 只盯源码目录 app/:别去监视 logs/(日志写入触发"检测→再写日志"回环)和 +# data/(sqlite 频繁写)。改 alembic/、.env、本脚本后请手动重启。 +exec "$PY" -m uvicorn app.main:app --host 0.0.0.0 --port 8770 --reload --reload-dir app