Files
countbot-ai__countbot/start_dev.py
T

121 lines
3.9 KiB
Python
Raw Normal View History

#!/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":
修复(核心): 编译版本路径和编码问题 + 批量读取优化 主要修复: 1. 统一路径管理 (backend/utils/paths.py) - 新增统一路径管理模块 - 编译版使用 sys.executable 定位 _internal 目录 - 开发版使用项目根目录 - 跨平台兼容 (Windows/macOS/Linux) - 修改 10 个后端文件使用统一路径 2. Unicode 编码错误修复 - 启动脚本设置 PYTHONIOENCODING=utf-8 - logger.py 包装 sys.stderr 为 UTF-8 - 使用 errors='replace' 避免崩溃 3. 循环导入修复 - 移除 backend/modules/agent/skills.py 自引用 4. macOS tkinter 线程错误 - start_desktop.py 检测主线程,非主线程只打印 5. 注释优化 - 移除冗长说明,保留核心信息 功能优化: 6. 批量文件读取 (backend/modules/tools/filesystem.py) - read_file 工具支持 paths 参数批量读取 - 示例: read_file(paths=['a.py', 'b.py', 'c.md']) - 减少工具调用次数,提升效率 - 上下文构建器提示使用批量读取 7. GitHub 工作流优化 (.github/workflows/build-desktop.yml) - 添加 backend.utils.paths 和 logger 隐藏导入 - 添加 backend.models.personality 隐藏导入 - 排除无用模块: playwright, pandas, numpy, PyQt, tkinter, torch 等 - 优化 collect-data 顺序 8. 文档更新 - requirements.txt: 依赖更新 修改文件统计: - 新增: 1 个文件 (backend/utils/paths.py) - 后端: 10 个文件 (路径管理相关) - 工具: 2 个文件 (filesystem.py, context.py) - 启动: 3 个脚本 (Windows编码问题) - 工作流: 1 个文件 (build-desktop.yml) - 文档: 1 个文件 ( requirements.txt) 测试: macOS 开发环境通过
2026-02-23 14:27:47 +08:00
# Python 3.7+ 支持
os.environ["PYTHONIOENCODING"] = "utf-8"
# 设置控制台代码页为 UTF-8
try:
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleCP(65001)
kernel32.SetConsoleOutputCP(65001)
except Exception:
pass
# 添加项目根目录到 Python 路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))
def main():
"""
启动应用(开发模式)
功能:
- 启动 FastAPI 应用服务器(开发模式)
- 启用热重载,文件更改自动重启
- 显示本地和网络访问地址
- 监控 backend 目录的文件变化
"""
import uvicorn
from loguru import logger
from backend.utils.logger import build_uvicorn_log_config
# 读取配置
host, port = resolve_bind_address()
apply_bind_env(host, port)
2026-02-23 05:49:26 +00:00
# 获取本地 IP 地址
local_ips = get_local_ips()
# 打印启动信息
logger.info("=" * 60)
logger.info("CountBot 开发模式启动中...")
logger.info("=" * 60)
2026-02-23 05:49:26 +00:00
try:
# 启动服务器前显示"服务器启动完成"消息和访问地址
logger.info("服务器启动完成!")
logger.info("=" * 60)
# 显示本地访问地址
logger.info(f"Local: http://localhost:{port}")
# 显示网络访问地址(如果监听了所有接口或用户明确设置了 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")
2026-02-23 05:49:26 +00:00
logger.info("-" * 60)
logger.info("热重载已启用 - 文件更改将自动重启")
logger.info("按下 Ctrl+C 停止服务器")
logger.info("=" * 60)
# 在 Windows 开发模式下uvicorn 的 reload 会切到 SelectorEventLoop
# 这会让 asyncio.create_subprocess_shell 无法使用。
run_kwargs = dict(
app="backend.app:app",
host=host,
port=port,
reload=True, # 开发模式启用热重载
reload_dirs=["backend"], # 监控 backend 目录
log_level="debug", # 开发模式使用 debug 日志级别
log_config=build_uvicorn_log_config(),
)
if sys.platform == "win32":
run_kwargs["loop"] = "none"
# 启动服务器(开发模式)
uvicorn.run(**run_kwargs)
2026-02-23 09:31:46 +00:00
except KeyboardInterrupt:
logger.info("Received keyboard interrupt")
except Exception as e:
logger.error(f"Server error: {e}")
raise
finally:
logger.info("Application shutdown complete")
if __name__ == "__main__":
main()