# 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", ".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 服务脚本(新增) if sys.platform == "win32": create_windows_service_scripts(deploy_dir) print(f"✅ 部署包: {deploy_dir}") 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()