""" LocalAgent 打包脚本 使用 PyInstaller 将项目打包成 Windows 可执行文件 使用方法: python build.py 打包完成后,可执行文件位于 dist/LocalAgent/ 目录下 """ import os import sys import shutil import subprocess from pathlib import Path # 项目根目录 PROJECT_ROOT = Path(__file__).parent def clean_build(): """清理之前的构建文件""" dirs_to_clean = ['build', 'dist'] files_to_clean = ['LocalAgent.spec'] for dir_name in dirs_to_clean: dir_path = PROJECT_ROOT / dir_name if dir_path.exists(): print(f"清理目录: {dir_path}") shutil.rmtree(dir_path) for file_name in files_to_clean: file_path = PROJECT_ROOT / file_name if file_path.exists(): print(f"清理文件: {file_path}") file_path.unlink() def build_exe(): """使用 PyInstaller 打包""" # PyInstaller 参数 args = [ 'pyinstaller', '--name=LocalAgent', # 程序名称 '--windowed', # 不显示控制台窗口(GUI 程序) # '--console', # 如果需要看到控制台输出,用这个替换上面的 '--onedir', # 打包成目录(比 onefile 启动更快) # '--onefile', # 如果想打包成单个 exe,用这个替换上面的 '--noconfirm', # 覆盖已有文件 '--clean', # 清理临时文件 # 添加数据文件 '--add-data=.env.example;.', # 配置模板 # 隐藏导入(PyInstaller 可能检测不到的模块) '--hidden-import=PIL', '--hidden-import=PIL.Image', '--hidden-import=openpyxl', '--hidden-import=docx', '--hidden-import=PyPDF2', '--hidden-import=chardet', '--hidden-import=dotenv', '--hidden-import=requests', '--hidden-import=tkinter', '--hidden-import=tkinter.ttk', '--hidden-import=tkinter.scrolledtext', '--hidden-import=tkinter.messagebox', '--hidden-import=tkinter.colorchooser', # 排除不需要的模块(减小体积) '--exclude-module=matplotlib', '--exclude-module=numpy', '--exclude-module=pandas', '--exclude-module=scipy', '--exclude-module=torch', '--exclude-module=tensorflow', # 入口文件 'main.py' ] print("=" * 50) print("开始打包 LocalAgent...") print("=" * 50) print(f"命令: {' '.join(args)}") print() # 执行打包 result = subprocess.run(args, cwd=PROJECT_ROOT) if result.returncode == 0: print() print("=" * 50) print("✅ 打包成功!") print("=" * 50) print() print(f"可执行文件位置: {PROJECT_ROOT / 'dist' / 'LocalAgent'}") print() print("使用说明:") print("1. 进入 dist/LocalAgent 目录") print("2. 复制 .env.example 为 .env 并配置 API Key") print("3. 运行 LocalAgent.exe") print() print("注意: 首次运行会自动创建 workspace 目录") # 创建 workspace 目录结构 dist_dir = PROJECT_ROOT / 'dist' / 'LocalAgent' if dist_dir.exists(): workspace = dist_dir / 'workspace' (workspace / 'input').mkdir(parents=True, exist_ok=True) (workspace / 'output').mkdir(parents=True, exist_ok=True) (workspace / 'logs').mkdir(parents=True, exist_ok=True) (workspace / 'codes').mkdir(parents=True, exist_ok=True) print("已创建 workspace 目录结构") # 复制 .env.example env_example = PROJECT_ROOT / '.env.example' if env_example.exists(): shutil.copy(env_example, dist_dir / '.env.example') print("已复制 .env.example") else: print() print("=" * 50) print("❌ 打包失败!") print("=" * 50) print("请检查错误信息") return result.returncode def main(): """主函数""" # 检查 PyInstaller 是否安装 try: import PyInstaller print(f"PyInstaller 版本: {PyInstaller.__version__}") except ImportError: print("错误: 未安装 PyInstaller") print("请运行: pip install pyinstaller") sys.exit(1) # 询问是否清理 response = input("是否清理之前的构建文件? (y/n) [y]: ").strip().lower() if response != 'n': clean_build() # 执行打包 return build_exe() if __name__ == '__main__': sys.exit(main())