#!/usr/bin/env python # -*- coding: utf-8 -*- """ OCR订单处理系统 - EXE打包脚本 ============================ 自动化打包脚本,包含所有必要的资源文件和配置 """ import os import sys import shutil import subprocess from pathlib import Path def clean_build(): """清理之前的构建文件""" print("清理构建目录...") dirs_to_clean = ['build', 'dist', '__pycache__'] for dir_name in dirs_to_clean: if os.path.exists(dir_name): shutil.rmtree(dir_name) print(f"已删除: {dir_name}") # 删除spec文件 spec_files = [f for f in os.listdir('.') if f.endswith('.spec')] for spec_file in spec_files: os.remove(spec_file) print(f"已删除: {spec_file}") def create_spec_file(): """创建PyInstaller spec文件""" spec_content = ''' # -*- mode: python ; coding: utf-8 -*- block_cipher = None # 需要包含的数据文件 added_files = [ ('config.ini', '.'), ('config/barcode_mappings.json', 'config/'), ('config/config.ini', 'config/'), ('templates/银豹-采购单模板.xls', 'templates/'), ('app', 'app'), ] # 需要隐式导入的模块 hidden_imports = [ 'tkinter', 'tkinter.ttk', 'tkinter.filedialog', 'tkinter.messagebox', 'tkinter.scrolledtext', 'pandas', 'numpy', 'openpyxl', 'xlrd', 'xlwt', 'xlutils', 'requests', 'configparser', 'threading', 'datetime', 'json', 're', 'subprocess', 'shutil', 'app.config.settings', 'app.services.ocr_service', 'app.services.order_service', 'app.services.tobacco_service', 'app.core.utils.dialog_utils', 'app.core.excel.converter', ] a = Analysis( ['启动器.py'], pathex=[], binaries=[], datas=added_files, hiddenimports=hidden_imports, 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='OCR订单处理系统', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, ) ''' with open('OCR订单处理系统.spec', 'w', encoding='utf-8') as f: f.write(spec_content) print("已创建spec文件: OCR订单处理系统.spec") def build_exe(): """构建EXE文件""" print("开始构建EXE文件...") try: result = subprocess.run([ 'pyinstaller', 'OCR订单处理系统.spec' ], check=True, capture_output=True, text=True) print("构建成功!") print(result.stdout) # 构建完成后,复制完整的配置文件到dist目录 dist_dir = Path('dist') # 复制包含API密钥的配置文件 config_file = Path('config/config.ini') if config_file.exists(): # 确保config目录存在 (dist_dir / 'config').mkdir(exist_ok=True) shutil.copy2(config_file, dist_dir / 'config') print(f"已复制配置文件到dist: {config_file} -> {dist_dir / 'config'}") # 复制完整的条码映射文件 barcode_mapping_file = Path('config/barcode_mappings.json') if barcode_mapping_file.exists(): shutil.copy2(barcode_mapping_file, dist_dir / 'config') print(f"已复制条码映射文件到dist: {barcode_mapping_file} -> {dist_dir / 'config'}") # 复制根目录的config.ini文件(覆盖空的配置文件) root_config_file = Path('config.ini') if root_config_file.exists(): shutil.copy2(root_config_file, dist_dir) print(f"已复制根配置文件到dist: {root_config_file} -> {dist_dir}") except subprocess.CalledProcessError as e: print(f"构建失败: {e}") print(f"错误输出: {e.stderr}") return False return True def create_portable_package(): """创建便携版打包""" print("创建便携版打包...") # 创建发布目录 release_dir = Path('release') if release_dir.exists(): shutil.rmtree(release_dir) release_dir.mkdir() # 复制exe文件 exe_file = Path('dist/OCR订单处理系统.exe') if exe_file.exists(): shutil.copy2(exe_file, release_dir) print(f"已复制: {exe_file} -> {release_dir}") # 创建必要的目录结构 dirs_to_create = ['data/input', 'data/output', 'logs', 'templates', 'config'] for dir_path in dirs_to_create: (release_dir / dir_path).mkdir(parents=True, exist_ok=True) print(f"已创建目录: {dir_path}") # 复制配置文件(包含API密钥) config_file = Path('config/config.ini') if config_file.exists(): shutil.copy2(config_file, release_dir / 'config') print(f"已复制配置文件: {config_file} -> {release_dir / 'config'}") else: print(f"警告: 配置文件不存在: {config_file}") # 复制完整的条码映射文件 barcode_mapping_file = Path('config/barcode_mappings.json') if barcode_mapping_file.exists(): shutil.copy2(barcode_mapping_file, release_dir / 'config') print(f"已复制条码映射文件: {barcode_mapping_file} -> {release_dir / 'config'}") else: print(f"警告: 条码映射文件不存在: {barcode_mapping_file}") # 复制根目录的config.ini文件 root_config_file = Path('config.ini') if root_config_file.exists(): shutil.copy2(root_config_file, release_dir) print(f"已复制根配置文件: {root_config_file} -> {release_dir}") else: print(f"警告: 根配置文件不存在: {root_config_file}") # 复制模板文件 template_file = Path('templates/银豹-采购单模板.xls') if template_file.exists(): shutil.copy2(template_file, release_dir / 'templates') print(f"已复制模板文件: {template_file} -> {release_dir / 'templates'}") else: print(f"警告: 模板文件不存在: {template_file}") # 创建README文件 readme_content = ''' # OCR订单处理系统 - 便携版 ## 使用说明 1. 双击 "OCR订单处理系统.exe" 启动程序 2. 将需要处理的图片文件放入 data/input 目录 3. 处理结果将保存在 data/output 目录 4. 日志文件保存在 logs 目录 ## 注意事项 - 首次运行时需要配置百度OCR API密钥 - 支持的图片格式:jpg, jpeg, png, bmp - 单个文件大小不超过4MB ## 目录结构 - OCR订单处理系统.exe - 主程序 - data/input/ - 输入图片目录 - data/output/ - 输出结果目录 - logs/ - 日志目录 ''' with open(release_dir / 'README.txt', 'w', encoding='utf-8') as f: f.write(readme_content) print("已创建README.txt") print(f"便携版打包完成,位置: {release_dir.absolute()}") def main(): """主函数""" print("=" * 50) print("OCR订单处理系统 - EXE打包工具") print("=" * 50) # 检查是否安装了PyInstaller try: subprocess.run(['pyinstaller', '--version'], check=True, capture_output=True) except (subprocess.CalledProcessError, FileNotFoundError): print("错误: 未安装PyInstaller") print("请运行: pip install pyinstaller") return 1 # 清理构建目录 clean_build() # 创建spec文件 create_spec_file() # 构建EXE if not build_exe(): return 1 # 创建便携版打包 create_portable_package() print("\n" + "=" * 50) print("打包完成!") print("EXE文件位置: dist/OCR订单处理系统.exe") print("便携版位置: release/") print("=" * 50) return 0 if __name__ == '__main__': sys.exit(main())