#!/usr/bin/env python3 """ 打包脚本 - 将Streamlit应用打包成exe文件 """ import os import sys import subprocess import shutil def install_pyinstaller(): """安装PyInstaller""" print("正在安装PyInstaller...") try: subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"]) print("✅ PyInstaller安装成功") return True except subprocess.CalledProcessError as e: print(f"❌ PyInstaller安装失败: {e}") return False def create_spec_file(): """创建PyInstaller spec文件""" spec_content = '''# -*- mode: python ; coding: utf-8 -*- import sys from PyInstaller.utils.hooks import collect_data_files, collect_submodules block_cipher = None a = Analysis( ['app.py'], pathex=[], binaries=[], datas=[ *collect_data_files('streamlit'), *collect_data_files('streamlit_ace'), *collect_data_files('streamlit_option_menu'), ('.env', '.') ], hiddenimports=[ 'streamlit', 'streamlit.web.cli', 'streamlit.runtime.scriptrunner', 'streamlit.proto', 'streamlit.config', 'streamlit.logger', 'streamlit.caching', 'streamlit.elements', 'streamlit.components', 'streamlit.server', 'streamlit.runtime', 'streamlit.delta_generator', 'streamlit.elements.lib.mutable_status_container', 'streamlit.elements.lib.dialog', 'streamlit.elements.lib.column_config', 'streamlit.elements.lib.metrics', 'streamlit.elements.lib.toast', 'streamlit.elements.lib.chat_message', 'streamlit.elements.lib.experimental_connection', 'streamlit.elements.lib.experimental_data_editor', 'streamlit.elements.lib.experimental_fragment', 'streamlit.elements.lib.experimental_get_query_params', 'streamlit.elements.lib.experimental_set_query_params', 'streamlit.elements.lib.experimental_user', 'streamlit.elements.lib.form_submit_button', 'streamlit.elements.lib.media', 'streamlit.elements.lib.progress', 'streamlit.elements.lib.snow', 'streamlit.elements.lib.spinner', 'streamlit.elements.lib.status', 'streamlit.elements.lib.tabs', 'streamlit.elements.lib.toast', 'streamlit.elements.lib.toggle', 'streamlit.elements.lib.tooltip', 'streamlit.elements.lib.widgets', 'openai', 'dotenv', 'requests', 'urllib3', 'certifi', 'charset_normalizer', 'idna', 'yaml', 'toml', 'PIL', 'numpy', 'pandas', 'altair', 'plotly', 'pydeck', 'bokeh', 'graphviz', 'keras', 'seaborn', 'sympy', 'streamlit_ace', 'streamlit_option_menu' ], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='multi_agent_decision_workshop', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, console=False, # 设置为False以隐藏控制台窗口 disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, ) ''' with open('app.spec', 'w', encoding='utf-8') as f: f.write(spec_content) print("✅ spec文件创建成功") def build_exe(): """构建exe文件""" print("开始构建exe文件...") try: # 使用spec文件构建 subprocess.check_call([sys.executable, "-m", "PyInstaller", "app.spec", "--clean"]) print("✅ exe文件构建成功") # 检查生成的文件 dist_dir = "dist" if os.path.exists(dist_dir): exe_path = os.path.join(dist_dir, "multi_agent_decision_workshop.exe") if os.path.exists(exe_path): file_size = os.path.getsize(exe_path) / (1024 * 1024) # MB print(f"📦 生成的exe文件: {exe_path}") print(f"📊 文件大小: {file_size:.2f} MB") return True print("❌ exe文件生成失败") return False except subprocess.CalledProcessError as e: print(f"❌ 构建失败: {e}") return False def create_launcher_bat(): """创建启动批处理文件""" bat_content = '''@echo off echo 正在启动多Agent决策工作坊... echo. cd /d "%~dp0" if exist "multi_agent_decision_workshop.exe" ( echo 启动应用程序... start "" "multi_agent_decision_workshop.exe" echo 应用程序已启动,请在浏览器中打开 http://localhost:8501 echo 按任意键退出... pause >nul ) else ( echo 错误:未找到 multi_agent_decision_workshop.exe echo 请确保此文件与exe文件在同一目录 pause ) ''' with open('启动程序.bat', 'w', encoding='gbk') as f: f.write(bat_content) print("✅ 启动批处理文件创建成功") def main(): """主函数""" print("🚀 开始打包多Agent决策工作坊应用...") print("=" * 50) # 检查当前目录 if not os.path.exists('app.py'): print("❌ 错误:请在项目根目录运行此脚本") return # 安装PyInstaller if not install_pyinstaller(): return # 创建spec文件 create_spec_file() # 构建exe if build_exe(): # 复制必要的文件到dist目录 dist_dir = "dist" if os.path.exists(dist_dir): # 复制.env文件 if os.path.exists('.env'): shutil.copy2('.env', os.path.join(dist_dir, '.env')) # 创建启动批处理文件 os.chdir(dist_dir) create_launcher_bat() print("\n🎉 打包完成!") print("📁 生成的文件在 'dist' 目录中") print("🚀 双击 '启动程序.bat' 即可运行应用") print("🌐 然后在浏览器中打开 http://localhost:8501") else: print("❌ dist目录不存在") else: print("❌ 打包失败") if __name__ == "__main__": main()