# 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) 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 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(" 运行: 执行 start.sh 或 start.bat") if __name__ == "__main__": main()