| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- # cythonize.py
- import os
- import sys
- import shutil
- from pathlib import Path
- import subprocess
- import time
- def print_banner():
- """打印标题"""
- print("=" * 60)
- print(" LongjoeAgent - Cython 编译工具")
- print("=" * 60)
- def check_environment():
- """检查环境"""
- print("\n🔍 检查环境...")
- # 检查Python
- if sys.version_info < (3, 7):
- print(f"❌ 需要Python 3.7+,当前: {sys.version}")
- return False
- # 检查依赖
- try:
- import Cython
- print(f"✅ Cython {Cython.__version__}")
- except ImportError:
- print("❌ 未安装Cython: pip install cython")
- return False
- try:
- import setuptools
- print(f"✅ setuptools {setuptools.__version__}")
- except ImportError:
- print("❌ 未安装setuptools: pip install setuptools wheel")
- return False
- return True
- def clean_build():
- """清理构建目录"""
- print("\n🧹 清理之前构建...")
- dirs_to_remove = ["build", "dist", "cython_build", "LongjoeAgent.egg-info"]
- for dir_name in dirs_to_remove:
- dir_path = Path(dir_name)
- if dir_path.exists():
- try:
- shutil.rmtree(dir_path)
- print(f" 已删除: {dir_name}")
- except:
- pass
- # 清理.c文件
- for c_file in Path(".").rglob("*.c"):
- try:
- c_file.unlink()
- except:
- pass
- def compile_project():
- """编译项目"""
- print("\n⚡ 开始编译...")
- start_time = time.time()
- # 运行setup.py
- result = subprocess.run(
- [sys.executable, "setup.py"], capture_output=True, text=True, encoding="utf-8"
- )
- if result.returncode != 0:
- print("❌ 编译失败!")
- if result.stderr:
- # 显示关键错误信息
- lines = result.stderr.split("\n")
- for line in lines:
- if "error" in line.lower() or "Error" in line:
- print(f" {line}")
- return False
- end_time = time.time()
- print(f"✅ 编译完成 ({end_time - start_time:.1f}秒)")
- # 显示编译结果
- show_compile_results()
- return True
- def show_compile_results():
- """显示编译结果"""
- compiled_dir = Path("build") / "compiled"
- if not compiled_dir.exists():
- print("❌ 编译目录不存在")
- return
- # 统计编译文件
- pyd_files = list(compiled_dir.rglob("*.pyd"))
- so_files = list(compiled_dir.rglob("*.so"))
- if pyd_files:
- print(f"\n📦 生成 {len(pyd_files)} 个 .pyd 文件:")
- for f in pyd_files[:5]:
- print(f" • {f.relative_to(compiled_dir)}")
- if len(pyd_files) > 5:
- print(f" ... 和 {len(pyd_files) - 5} 个其他文件")
- elif so_files:
- print(f"\n📦 生成 {len(so_files)} 个 .so 文件:")
- for f in so_files[:5]:
- print(f" • {f.relative_to(compiled_dir)}")
- if len(so_files) > 5:
- print(f" ... 和 {len(so_files) - 5} 个其他文件")
- else:
- print("❌ 未找到编译文件")
- def create_deployment():
- """创建部署包"""
- print("\n📦 创建部署包...")
- compiled_dir = Path("build") / "compiled"
- deploy_dir = Path("build") / "deploy"
- if not compiled_dir.exists():
- print("❌ 编译目录不存在")
- return
- # 清理旧的部署包
- if deploy_dir.exists():
- shutil.rmtree(deploy_dir)
- # 复制编译文件
- deploy_dir.mkdir(parents=True, exist_ok=True)
- for src_file in compiled_dir.rglob("*"):
- if src_file.is_file():
- rel_path = src_file.relative_to(compiled_dir)
- dst_file = deploy_dir / rel_path
- dst_file.parent.mkdir(parents=True, exist_ok=True)
- shutil.copy2(src_file, dst_file)
- # 复制必要文件
- essential_files = [
- "app.py",
- "get_device_id.py",
- ".env.example",
- "requirements.txt",
- ".registration.example",
- ]
- for file_name in essential_files:
- src = Path(file_name)
- if src.exists():
- dst = deploy_dir / file_name
- shutil.copy2(src, dst)
- print(f" 复制: {file_name}")
- # 复制 config 目录下的 JSON 配置文件
- config_src = Path("config")
- if config_src.exists():
- config_dst = deploy_dir / "config"
- config_dst.mkdir(exist_ok=True)
- # 复制所有 JSON 文件
- json_files = list(config_src.rglob("*.json"))
- for json_file in json_files:
- if json_file.is_file():
- rel_path = json_file.relative_to(config_src)
- dst_file = config_dst / rel_path
- dst_file.parent.mkdir(parents=True, exist_ok=True)
- shutil.copy2(json_file, dst_file)
- print(f" 复制配置文件: config/{rel_path}")
- if json_files:
- print(f"✅ 已复制 {len(json_files)} 个配置文件")
- # 创建日志目录
- (deploy_dir / "chat_logs").mkdir(exist_ok=True)
- # 创建启动脚本
- create_start_scripts(deploy_dir)
- # 创建 Windows 服务脚本,获取当前设备ID脚本
- if sys.platform == "win32":
- create_windows_service_scripts(deploy_dir)
- create_get_device_id_script(deploy_dir)
- print(f"✅ 部署包: {deploy_dir}")
- def create_get_device_id_script(deploy_dir):
- """创建获取设备ID脚本"""
- print(" 创建获取设备ID脚本...")
- bat_content = """@echo off
- chcp 65001 >nul
- echo === LongjoeAgent ===
- echo.
- REM 检查Python
- python --version >nul 2>&1
- if errorlevel 1 (
- echo 错误: 未找到Python
- pause
- exit /b 1
- )
- REM 获取当前设备ID
- echo 获取当前设备ID...
- python get_device_id.py
- pause
- """
- bat_file = deploy_dir / "get_device_id.bat"
- bat_file.write_text(bat_content, encoding="utf-8")
- def create_start_scripts(deploy_dir):
- """创建启动脚本"""
- # Windows
- bat_content = """@echo off
- chcp 65001 >nul
- echo === LongjoeAgent ===
- echo.
- REM 检查Python
- python --version >nul 2>&1
- if errorlevel 1 (
- echo 错误: 未找到Python
- pause
- exit /b 1
- )
- REM 启动
- echo 启动服务...
- python app.py
- pause
- """
- bat_file = deploy_dir / "start.bat"
- bat_file.write_text(bat_content, encoding="utf-8")
- # Linux/Mac
- sh_content = """#!/bin/bash
- echo "=== LongjoeAgent ==="
- # 检查Python
- if ! command -v python3 &> /dev/null; then
- echo "错误: 未找到Python3"
- exit 1
- fi
- # 启动
- echo "启动服务..."
- python3 app.py
- """
- sh_file = deploy_dir / "start.sh"
- sh_file.write_text(sh_content, encoding="utf-8")
- if sys.platform != "win32":
- os.chmod(sh_file, 0o755)
- print(" 创建启动脚本: start.bat, start.sh")
- def create_windows_service_scripts(deploy_dir):
- """创建 Windows 服务管理脚本"""
- print(" 创建 Windows 服务脚本...")
- # 检查本地 nssm.exe
- nssm_exe = Path("nssm.exe")
- if not nssm_exe.exists():
- print(" ⚠️ 未找到 nssm.exe,跳过服务脚本创建")
- return
- # 复制 nssm.exe 到部署目录
- nssm_dst = deploy_dir / "nssm.exe"
- shutil.copy2(nssm_exe, nssm_dst)
- print(" ✅ 复制 nssm.exe")
- # 服务安装脚本
- install_bat = """@echo off
- chcp 65001 >nul
- echo ========================================
- echo LongjoeAgent Windows Service Install
- echo ========================================
- echo.
- REM 检查是否以管理员权限运行
- net session >nul 2>&1
- if %errorlevel% neq 0 (
- echo Error: 请以管理员权限运行此脚本!
- echo 请右键点击此脚本 -> "以管理员身份运行"
- pause
- exit /b 1
- )
- REM 动态获取脚本所在目录
- set "PROJECT_DIR=%~dp0"
- set "PROJECT_DIR=%PROJECT_DIR:~0,-1%"
- echo 项目目录: %PROJECT_DIR%
- REM 检查必要文件是否存在
- if not exist "%PROJECT_DIR%\\nssm.exe" (
- echo 错误: nssm.exe 未在项目目录中找到!
- pause
- exit /b 1
- )
- if not exist "%PROJECT_DIR%\\app.py" (
- echo 错误: app.py 未在项目目录中找到!
- pause
- exit /b 1
- )
- REM 动态查找Python安装路径
- echo 搜索Python安装...
- for /f "delims=" %%i in ('where python') do (
- set "PYTHON_PATH=%%i"
- goto :found_python
- )
- :found_python
- if not defined PYTHON_PATH (
- echo 错误: 未找到Python!
- echo 请安装 Python 3.7+ 并确保其在 PATH 中
- pause
- exit /b 1
- )
- echo 找到Python: %PYTHON_PATH%
- REM 停止并移除现有服务
- echo Unstall Service
- net stop LongjoeAI >nul 2>&1
- timeout /t 2 /nobreak >nul
- "%PROJECT_DIR%\\nssm.exe" remove LongjoeAI confirm >nul 2>&1
- REM 关键修正:使用正确的引号格式(模仿您的成功命令)
- echo 安装 LongjoeAI 服务...
- "%PROJECT_DIR%\\nssm.exe" install LongjoeAI "cmd" "/c cd /d "%PROJECT_DIR%" && "%PYTHON_PATH%" app.py"
- if errorlevel 1 (
- echo 错误: 服务安装失败!
- echo.
- echo 调试信息:
- echo 项目目录: %PROJECT_DIR%
- echo Python 路径: %PYTHON_PATH%
- )
- REM 配置服务参数
- echo 配置服务参数...
- "%PROJECT_DIR%\\nssm.exe" set LongjoeAI DisplayName "Longjoe AI Agent Service"
- "%PROJECT_DIR%\\nssm.exe" set LongjoeAI Description "龙嘉软件AI助手服务"
- echo.
- echo LongjoeAI 服务安装完成!
- goto :start_service
- :start_service
- echo.
- echo Starting service...
- net start LongjoeAI
- if %errorlevel% equ 0 (
- echo SUCCESS: Service started successfully!
- echo.
-
- ) else (
- echo ERROR: Service failed to start
- echo.
- )
- echo.
- pause
- """
- # 服务卸载脚本
- uninstall_bat = """@echo off
- chcp 65001 >nul
- echo ========================================
- echo LongjoeAI Service Uninstall
- echo ========================================
- echo.
- REM 检查是否以管理员权限运行
- net session >nul 2>&1
- if %errorlevel% neq 0 (
- echo 错误: 请以管理员权限运行此脚本!
- echo 请右键点击此脚本 -> "以管理员身份运行"
- pause
- exit /b 1
- )
- REM 动态获取项目目录
- set "PROJECT_DIR=%~dp0"
- set "PROJECT_DIR=%PROJECT_DIR:~0,-1%"
- echo 停止服务...
- net stop LongjoeAI >nul 2>&1
- timeout /t 3 /nobreak >nul
- echo 卸载服务...
- "%PROJECT_DIR%\\nssm.exe" remove LongjoeAI confirm >nul 2>&1
- if errorlevel 1 (
- echo 尝试强制删除...
- sc delete LongjoeAI >nul 2>&1
- )
- echo LongjoeAI 服务卸载成功!
- echo.
- pause
- """
- # 服务管理脚本
- manage_bat = """@echo off
- chcp 65001 >nul
- echo ========================================
- echo LongjoeAI Service Management
- echo ========================================
- echo.
- set "PROJECT_DIR=%~dp0"
- set "PROJECT_DIR=%PROJECT_DIR:~0,-1%"
- echo 1. 启动服务
- echo 2. 停止服务
- echo 3. 重启服务
- echo 4. 服务状态
- echo 5. Exit
- echo.
- set /p choice=请选择操作 (1-5):
- if "%choice%"=="1" (
- net start LongjoeAI
- if %errorlevel% equ 0 echo Service started successfully.
- ) else if "%choice%"=="2" (
- net stop LongjoeAI
- if %errorlevel% equ 0 echo Service stopped successfully.
- ) else if "%choice%"=="3" (
- net stop LongjoeAI
- timeout /t 2 /nobreak >nul
- net start LongjoeAI
- if %errorlevel% equ 0 echo Service restarted successfully.
- ) else if "%choice%"=="4" (
- sc query LongjoeAI
- ) else if "%choice%"=="5" (
- exit
- ) else (
- echo 错误: 无效选择!
- )
- echo.
- pause
- """
- # 写入脚本文件
- (deploy_dir / "service_install.bat").write_text(install_bat, encoding="utf-8")
- (deploy_dir / "service_uninstall.bat").write_text(uninstall_bat, encoding="utf-8")
- (deploy_dir / "service_manage.bat").write_text(manage_bat, encoding="utf-8")
- print(
- " ✅ 创建服务脚本: service_install.bat, service_uninstall.bat, service_manage.bat"
- )
- def main():
- """主函数"""
- print_banner()
- # 1. 检查环境
- if not check_environment():
- sys.exit(1)
- # 2. 清理
- clean_build()
- # 3. 编译
- if not compile_project():
- sys.exit(1)
- # 4. 创建部署包
- create_deployment()
- # 5. 完成
- print("\n" + "=" * 60)
- print("🎉 编译完成!")
- print("=" * 60)
- print("\n📁 文件结构:")
- print(" • 源代码: 保持不变")
- print(" • 编译文件: build/compiled/")
- print(" • 部署包: build/deploy/")
- print("\n🚀 使用方法:")
- print(" 开发: python app.py")
- print(" 部署: 复制 build/deploy/ 到服务器")
- print(" 运行: 执行 service_install.bat")
- if __name__ == "__main__":
- main()
|