""" Mypyc 编译脚本 用于将核心 Python 模块编译为 C 扩展,以提升性能。 使用方法: python setup_mypyc.py build_ext --inplace 注意: 1. 需要安装 C 编译器 (Windows 上需要 Visual Studio Build Tools, Linux 上需要 GCC)。 2. 编译后的文件 (.pyd 或 .so) 是平台相关的,不能跨平台复制。 3. 建议在部署的目标环境 (Linux) 上运行此脚本。 """ import os import sys import subprocess # 基础模块列表 # 注意:Mypyc 对动态特性支持有限,只选择计算密集或类型明确的模块 modules = [ # 工具模块 'core/utils/json_utils.py', # JSON 处理 'core/utils/executor.py', # 代码执行引擎 'core/utils/singleton.py', # 单例模式基类 'core/utils/exceptions.py', # 自定义异常 'core/utils/logger.py', # 日志模块 # 核心管理模块 'core/managers/command_manager.py', # 指令匹配和分发 'core/managers/admin_manager.py', # 管理员管理 'core/managers/permission_manager.py', # 权限管理 'core/managers/plugin_manager.py', # 插件管理器 # 核心基础模块 'core/ws.py', # WebSocket 核心 'core/bot.py', # Bot 核心抽象 'core/config_loader.py', # 配置加载 'core/config_models.py', # 配置模型 'core/permission.py', # 权限枚举 # API 基础模块 'core/api/base.py', # API 基础类 # 数据模型(适合编译的高频使用数据类) 'models/message.py', # 消息段模型 'models/sender.py', # 发送者模型 'models/objects.py', # API 响应数据模型 ] # 注意:事件模型文件暂时不编译,因为它们与 mypyc 存在兼容性问题 # mypyc 对某些数据类特性和继承结构的支持有限,会导致运行时错误 # event_models = glob.glob('models/events/*.py') # event_models = [m for m in event_models if not m.endswith('__init__.py')] # modules.extend(event_models) # 确保文件存在 valid_modules = [] for m in modules: if os.path.exists(m): valid_modules.append(m) else: print(f"Warning: Module {m} not found, skipping.") if not valid_modules: print("No valid modules found to compile.") sys.exit(1) print(f"Compiling the following modules with mypyc: {valid_modules}") # 使用 mypyc 命令行工具单独编译每个模块,确保位置正确 success_count = 0 for module_path in valid_modules: print(f"\nCompiling {module_path}...") try: # 直接调用 mypyc 命令行工具 result = subprocess.run( [sys.executable, '-m', 'mypyc', module_path], capture_output=True, text=True, check=True ) # 验证编译产物是否在正确位置 module_name = module_path.replace('.py', '') pyd_path = module_name + '.cp314-win_amd64.pyd' mypyc_path = module_name + '__mypyc.cp314-win_amd64.pyd' if os.path.exists(pyd_path): print(f" ✓ Compiled successfully: {pyd_path}") success_count += 1 else: # 检查 build 目录中是否有编译产物 build_pyd_path = os.path.join('build', 'lib.win-amd64-cpython-314', pyd_path) if os.path.exists(build_pyd_path): # 如果在 build 目录中,复制到正确位置 os.makedirs(os.path.dirname(pyd_path), exist_ok=True) import shutil shutil.copy2(build_pyd_path, pyd_path) shutil.copy2(os.path.join('build', 'lib.win-amd64-cpython-314', mypyc_path), mypyc_path) print(f" ✓ Compiled successfully (copied from build directory): {pyd_path}") success_count += 1 else: print(" ✗ Compiled but cannot find pyd file") print(f" Build output:\n{result.stdout[:500]}...") except subprocess.CalledProcessError as e: print(f" ✗ Compilation failed with exit code {e.returncode}") print(f" Error:\n{e.stderr[:500]}...") except Exception as e: print(f" ✗ Unexpected error: {e}") print("\n--- Compilation Summary ---") print(f"Total modules: {len(valid_modules)}") print(f"Successfully compiled: {success_count}") print(f"Failed: {len(valid_modules) - success_count}") if success_count == 0: print("No modules were compiled successfully. Exiting with error.") sys.exit(1)