- 新增 `/status` 指令,展示机器人运行状态和系统指标 - 实现Redis Lua脚本支持原子化计数器操作 - 添加消息收发统计功能 - 完善文档,包括插件开发和性能优化指南 - 重构WebSocket连接池,增加健康检查机制 - 移除旧版编译脚本,优化项目结构
205 lines
6.4 KiB
Python
205 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
自动化跨平台 Python 模块编译脚本 (v2.2)
|
||
|
||
将核心 Python 模块编译为机器码 (.pyd 或 .so) 以提升性能。
|
||
此版本实现了全自动清理和保守的编译范围,以确保稳定性。
|
||
|
||
支持的平台:
|
||
- Windows: 生成 .pyd 文件
|
||
- Linux: 生成 .so 文件
|
||
|
||
使用方法:
|
||
python scripts/compile_machine_code.py
|
||
|
||
脚本会自动执行以下步骤:
|
||
1. 清理所有旧的编译文件 (.pyd, .so) 和 build 目录。
|
||
2. 编译模块列表中所有兼容的模块。
|
||
3. 列出所有成功编译的模块。
|
||
|
||
注意:
|
||
1. 需要安装 C 编译器 (Windows 上需要 Visual Studio Build Tools, Linux 上需要 GCC)
|
||
2. 需要安装 mypyc: pip install mypyc
|
||
3. 编译后的文件是平台相关的,不能跨平台复制。
|
||
"""
|
||
import os
|
||
import sys
|
||
import glob
|
||
import subprocess
|
||
import shutil
|
||
|
||
# --- 配置区 ---
|
||
|
||
# 检测当前平台和 Python 版本
|
||
PLATFORM = sys.platform
|
||
PYTHON_VERSION = f"{sys.version_info.major}{sys.version_info.minor}"
|
||
|
||
if PLATFORM.startswith('win'):
|
||
EXTENSION = '.pyd'
|
||
BUILD_PREFIX = f'cp{PYTHON_VERSION}-win_amd64'
|
||
BUILD_PATH = os.path.join('build', f'lib.win-amd64-cpython-{PYTHON_VERSION}')
|
||
elif PLATFORM.startswith('linux'):
|
||
EXTENSION = '.so'
|
||
BUILD_PREFIX = f'cp{PYTHON_VERSION}-x86_64-linux-gnu'
|
||
BUILD_PATH = os.path.join('build', f'lib.linux-x86_64-cpython-{PYTHON_VERSION}')
|
||
else:
|
||
print(f"不支持的平台: {PLATFORM}")
|
||
sys.exit(1)
|
||
|
||
# 经过测试的稳定编译模块列表
|
||
MODULES = [
|
||
# 工具模块
|
||
'core/utils/executor.py',
|
||
'core/utils/exceptions.py',
|
||
'core/utils/logger.py',
|
||
|
||
# 核心基础模块
|
||
'core/ws.py',
|
||
'core/config_loader.py',
|
||
|
||
# 数据模型 (仅包含安全的、无复杂元类的部分)
|
||
'models/message.py',
|
||
'models/sender.py',
|
||
'models/objects.py',
|
||
]
|
||
|
||
# --- 功能函数 ---
|
||
|
||
def list_compiled_modules():
|
||
"""列出已编译的模块"""
|
||
print(f"\n已编译的 {PLATFORM} 模块:")
|
||
print("=" * 50)
|
||
|
||
compiled_files = glob.glob(f'**/*{EXTENSION}', recursive=True)
|
||
compiled_files = [f for f in compiled_files if 'venv' not in f and '.venv' not in f]
|
||
|
||
if compiled_files:
|
||
for f in sorted(compiled_files):
|
||
try:
|
||
size = os.path.getsize(f) // 1024
|
||
print(f"{f} ({size} KB)")
|
||
except FileNotFoundError:
|
||
continue
|
||
else:
|
||
print(f"未找到已编译的 {EXTENSION} 文件")
|
||
|
||
print(f"\n总计: {len(compiled_files)} 个文件")
|
||
|
||
def clean_compiled_files():
|
||
"""清理所有编译生成的文件和目录"""
|
||
print("--- 步骤 1: 清理旧的编译文件 ---")
|
||
|
||
compiled_files = glob.glob(f'**/*{EXTENSION}', recursive=True)
|
||
compiled_files = [f for f in compiled_files if 'venv' not in f and '.venv' not in f]
|
||
|
||
if compiled_files:
|
||
for f in sorted(compiled_files):
|
||
try:
|
||
os.remove(f)
|
||
print(f" 已删除: {f}")
|
||
except Exception as e:
|
||
print(f" 删除失败 {f}: {e}")
|
||
else:
|
||
print(" 没有可清理的文件")
|
||
|
||
if os.path.exists('build'):
|
||
try:
|
||
shutil.rmtree('build')
|
||
print(" 已删除 build 目录")
|
||
except Exception as e:
|
||
print(f" 删除 build 目录失败: {e}")
|
||
print("-" * 35)
|
||
|
||
def compile_module(module_path):
|
||
"""编译单个模块"""
|
||
print(f"\n编译: {module_path}")
|
||
|
||
try:
|
||
result = subprocess.run(
|
||
[sys.executable, '-m', 'mypyc', module_path],
|
||
capture_output=True,
|
||
check=True,
|
||
text=True,
|
||
encoding='utf-8',
|
||
errors='replace'
|
||
)
|
||
|
||
# 智能查找编译产物
|
||
base_name = os.path.basename(module_path).replace('.py', '')
|
||
search_pattern = os.path.join(BUILD_PATH, '**', f'{base_name}.*{EXTENSION}')
|
||
|
||
found_files = glob.glob(search_pattern, recursive=True)
|
||
|
||
if found_files:
|
||
build_module_path = found_files[0]
|
||
dest_path = os.path.join(os.path.dirname(module_path), os.path.basename(build_module_path))
|
||
|
||
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
||
shutil.copy2(build_module_path, dest_path)
|
||
print(f" ✓ 编译成功: {dest_path}")
|
||
return True
|
||
else:
|
||
print(f" ✗ 编译失败:在 {BUILD_PATH} 中找不到编译产物")
|
||
if result.stdout: print(f" 输出: {result.stdout[:500]}...")
|
||
if result.stderr: print(f" 错误: {result.stderr[:500]}...")
|
||
return False
|
||
|
||
except subprocess.CalledProcessError as e:
|
||
print(f" ✗ 编译失败 (Exit Code: {e.returncode})")
|
||
if e.stdout: print(f" 输出: {e.stdout[:500]}...")
|
||
if e.stderr: print(f" 错误: {e.stderr[:500]}...")
|
||
return False
|
||
except Exception as e:
|
||
print(f" ✗ 编译时发生意外错误: {e}")
|
||
return False
|
||
|
||
def compile_all_modules():
|
||
"""编译所有指定的模块"""
|
||
print("\n--- 步骤 2: 开始编译模块 ---")
|
||
|
||
valid_modules = []
|
||
for module in MODULES:
|
||
if os.path.exists(module):
|
||
valid_modules.append(module)
|
||
else:
|
||
print(f"警告: 模块 {module} 不存在,已跳过")
|
||
|
||
print(f"\n找到 {len(valid_modules)} 个有效模块进行编译。")
|
||
|
||
success_count = 0
|
||
failed_modules = []
|
||
|
||
for module in valid_modules:
|
||
if compile_module(module):
|
||
success_count += 1
|
||
else:
|
||
failed_modules.append(module)
|
||
|
||
print("\n" + "=" * 50)
|
||
print(f"编译完成: {success_count}/{len(valid_modules)} 个模块成功")
|
||
|
||
if failed_modules:
|
||
print(f"失败模块: {failed_modules}")
|
||
print("✗ 部分模块编译失败")
|
||
else:
|
||
print("✓ 所有模块编译成功")
|
||
print("=" * 50)
|
||
|
||
def main():
|
||
"""主函数:执行清理、编译和列出结果的全过程"""
|
||
if not (sys.version_info.major == 3 and sys.version_info.minor >= 8):
|
||
print("警告: 推荐使用 Python 3.8+ 以获得最佳性能。")
|
||
|
||
try:
|
||
import mypyc
|
||
except ImportError:
|
||
print("错误: 未安装 mypyc,请运行: pip install mypyc")
|
||
sys.exit(1)
|
||
|
||
clean_compiled_files()
|
||
compile_all_modules()
|
||
list_compiled_modules()
|
||
|
||
if __name__ == '__main__':
|
||
main()
|