构建(运行时): 统一启动环境变量并优化本地启动体验

This commit is contained in:
Countbot-ai
2026-04-07 00:42:23 +08:00
parent a04e6bb3d9
commit 2ec2f37e50
5 changed files with 189 additions and 99 deletions
+53 -42
View File
@@ -1,17 +1,22 @@
#!/usr/bin/env python3
"""
CountBot 应用启动脚本
开发模式启动,支持热重载
支持本地网络 IP 监控,类似 Vue3 启动模式
"""
import os
import sys
from pathlib import Path
from backend.utils.network import get_local_ips
# Windows 平台强制 UTF-8 编码,避免 GBK 编码错误
if sys.platform == "win32":
#!/usr/bin/env python3
"""
CountBot 应用启动脚本
开发模式启动,支持热重载
支持本地网络 IP 监控,类似 Vue3 启动模式
"""
import os
import sys
from pathlib import Path
from backend.utils.network import get_local_ips
from backend.utils.runtime_env import (
apply_bind_env,
is_public_bind_host,
resolve_bind_address,
)
# Windows 平台强制 UTF-8 编码,避免 GBK 编码错误
if sys.platform == "win32":
# Python 3.7+ 支持
os.environ["PYTHONIOENCODING"] = "utf-8"
# 设置控制台代码页为 UTF-8
@@ -28,24 +33,24 @@ project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))
def main():
def main():
"""
启动应用(开发模式)
功能:
- 启动 FastAPI 应用服务器(开发模式)
- 启用热重载,文件更改自动重启
- 显示本地和网络访问地址
- 监控 backend 目录的文件变化
"""
功能:
- 启动 FastAPI 应用服务器(开发模式)
- 启用热重载,文件更改自动重启
- 显示本地和网络访问地址
- 监控 backend 目录的文件变化
"""
import uvicorn
from loguru import logger
from backend.utils.logger import build_uvicorn_log_config
# 读取配置
host = os.getenv("HOST", "127.0.0.1")
port = int(os.getenv("PORT", "8000"))
host, port = resolve_bind_address()
apply_bind_env(host, port)
# 获取本地 IP 地址
local_ips = get_local_ips()
@@ -64,31 +69,32 @@ def main():
logger.info(f"Local: http://localhost:{port}")
# 显示网络访问地址(如果监听了所有接口或用户明确设置了 0.0.0.0
if host in ["0.0.0.0", "::"]:
if local_ips:
for ip in local_ips:
logger.info(f"Network: http://{ip}:{port}")
else:
logger.info("Network: (无法检测到本地 IP 地址)")
logger.info(f"提示: 请检查网络连接或手动访问 http://<your-ip>:{port}")
else:
# 即使监听 127.0.0.1,也显示可用的网络 IP 供参考
if local_ips:
logger.info(f"Network: http://{host}:{port}")
logger.info("提示: 如需从其他设备访问,请设置 HOST=0.0.0.0")
logger.info(f"可用网络 IP: {', '.join(local_ips)}")
else:
logger.info(f"Network: http://{host}:{port}")
logger.info("提示: 如需从其他设备访问,请设置 HOST=0.0.0.0")
if is_public_bind_host(host):
if local_ips:
for ip in local_ips:
logger.info(f"Network: http://{ip}:{port}")
else:
logger.info("Network: (无法检测到本地 IP 地址)")
logger.info(f"提示: 请检查网络连接或手动访问 http://<your-ip>:{port}")
else:
# 即使监听 127.0.0.1,也显示可用的网络 IP 供参考
if local_ips:
logger.info(f"Network: http://{host}:{port}")
logger.info("提示: 如需从其他设备访问,请设置 COUNTBOT_HOST=0.0.0.0")
logger.info(f"可用网络 IP: {', '.join(local_ips)}")
else:
logger.info(f"Network: http://{host}:{port}")
logger.info("提示: 如需从其他设备访问,请设置 COUNTBOT_HOST=0.0.0.0")
logger.info("-" * 60)
logger.info("热重载已启用 - 文件更改将自动重启")
logger.info("按下 Ctrl+C 停止服务器")
logger.info("=" * 60)
# 启动服务器(开发模式)
uvicorn.run(
"backend.app:app",
# 在 Windows 开发模式下uvicorn 的 reload 会切到 SelectorEventLoop
# 这会让 asyncio.create_subprocess_shell 无法使用。
run_kwargs = dict(
app="backend.app:app",
host=host,
port=port,
reload=True, # 开发模式启用热重载
@@ -96,6 +102,11 @@ def main():
log_level="debug", # 开发模式使用 debug 日志级别
log_config=build_uvicorn_log_config(),
)
if sys.platform == "win32":
run_kwargs["loop"] = "none"
# 启动服务器(开发模式)
uvicorn.run(**run_kwargs)
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e: