#!/usr/bin/env python3 """ 完全清理环境并重新构建的脚本 """ import os import sys import shutil import glob import subprocess from pathlib import Path def deep_cleanup(): """深度清理所有相关文件""" print("开始深度清理...") # 要清理的目录 dirs_to_clean = [ "build", "dist", "__pycache__", ".pytest_cache", "*.egg-info" ] # 要清理的文件模式 files_to_clean = [ "*.exe", "*.spec", "*_encrypted*", "setup_main.py", "setup_validator.py", "*.pyc", "*.pyo" ] # 清理目录 for dir_pattern in dirs_to_clean: for dir_path in glob.glob(dir_pattern): if os.path.exists(dir_path): print(f"删除目录: {dir_path}") try: shutil.rmtree(dir_path) except Exception as e: print(f"删除 {dir_path} 失败: {e}") # 清理文件 for file_pattern in files_to_clean: for file_path in glob.glob(file_pattern): if os.path.exists(file_path): print(f"删除文件: {file_path}") try: os.remove(file_path) except Exception as e: print(f"删除 {file_path} 失败: {e}") # 清理Python缓存 for root, dirs, files in os.walk("."): for dir_name in dirs[:]: if dir_name == "__pycache__": pycache_path = os.path.join(root, dir_name) print(f"删除缓存: {pycache_path}") try: shutil.rmtree(pycache_path) dirs.remove(dir_name) except Exception as e: print(f"删除缓存失败: {e}") print("清理完成") def create_single_file_setup(script_name, output_name, base_type="Console"): """创建单文件构建的setup.py""" setup_content = f''' import sys from cx_Freeze import setup, Executable # 基础构建选项 build_exe_options = {{ "packages": [ "mysql.connector", "cryptography", "uuid", "hashlib", "datetime", "platform", "subprocess", "json", "tempfile", "atexit", "ctypes" ], "build_exe": "dist_{output_name.replace('.exe', '')}", "excludes": ["unittest", "test"] }} # 如果是主程序,添加tkinter和pyperclip if "{script_name}" == "main.py": build_exe_options["packages"].extend(["tkinter", "pyperclip"]) executables = [ Executable("{script_name}", base="{base_type}") ] setup( name="{output_name.replace('.exe', '')}", version="1.0", options={{"build_exe": build_exe_options}}, executables=executables ) ''' return setup_content def build_single_executable(script_name, output_name, base_type="Console"): """构建单个可执行文件""" print(f"构建 {script_name} -> {output_name}") # 创建临时setup文件 setup_filename = f"setup_{output_name.replace('.exe', '')}.py" setup_content = create_single_file_setup(script_name, output_name, base_type) try: with open(setup_filename, "w", encoding="utf-8") as f: f.write(setup_content) # 运行构建 result = subprocess.run( [sys.executable, setup_filename, "build"], capture_output=True, text=True, cwd="." ) success = result.returncode == 0 if success: print(f"{output_name} 构建成功") else: print(f"{output_name} 构建失败:") print(result.stderr) return success except Exception as e: print(f"构建 {output_name} 时发生异常: {e}") return False finally: # 清理临时文件 if os.path.exists(setup_filename): try: os.remove(setup_filename) except: pass def organize_final_dist(): """整理最终的发布目录""" print("整理最终发布目录...") final_dir = Path("dist_final") final_dir.mkdir(exist_ok=True) # 收集所有构建的文件 dist_dirs = [d for d in Path(".").iterdir() if d.is_dir() and d.name.startswith("dist_")] all_files = {} for dist_dir in dist_dirs: for file_path in dist_dir.rglob("*"): if file_path.is_file(): all_files[file_path.name] = file_path # 复制文件到最终目录 for filename, filepath in all_files.items(): dest_path = final_dir / filename if not dest_path.exists() or filename.endswith('.exe'): try: shutil.copy2(filepath, dest_path) print(f"复制: {filename}") except Exception as e: print(f"复制 {filename} 失败: {e}") # 重命名主程序 main_exe = final_dir / "main.exe" target_exe = final_dir / "EXE加密工具.exe" if main_exe.exists() and not target_exe.exists(): try: main_exe.rename(target_exe) print("主程序重命名为: EXE加密工具.exe") except Exception as e: print(f"重命名失败: {e}") # 清理临时构建目录 for dist_dir in dist_dirs: try: shutil.rmtree(dist_dir) except: pass print(f"最终文件已整理到: {final_dir.absolute()}") return final_dir def try_pyinstaller_fallback(): """尝试使用PyInstaller作为备选方案""" print("尝试使用PyInstaller作为备选方案...") try: # 检查PyInstaller是否可用 result = subprocess.run([sys.executable, "-c", "import PyInstaller"], capture_output=True) if result.returncode != 0: print("PyInstaller未安装,正在安装...") subprocess.run([sys.executable, "-m", "pip", "install", "pyinstaller"], check=True) # 使用PyInstaller构建 commands = [ [sys.executable, "-m", "PyInstaller", "--onefile", "--windowed", "--name=EXE加密工具", "main.py"], [sys.executable, "-m", "PyInstaller", "--onefile", "--console", "validator.py"] ] for cmd in commands: print(f"运行: {' '.join(cmd)}") result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: print(f"PyInstaller构建失败: {result.stderr}") return False print("PyInstaller构建成功!文件位于 dist/ 目录") return True except Exception as e: print(f"PyInstaller构建异常: {e}") return False def main(): """主函数""" print("=== EXE加密工具构建脚本 ===") # 1. 深度清理 deep_cleanup() # 2. 尝试使用cx_Freeze分别构建 print("\n尝试使用cx_Freeze构建...") builds = [ ("main.py", "main.exe", "Win32GUI"), ("validator.py", "validator.exe", "Console") ] all_success = True for script, output, base in builds: if not build_single_executable(script, output, base): all_success = False break if all_success: final_dir = organize_final_dist() print(f"\n✅ cx_Freeze构建成功!") print(f"📁 文件位置: {final_dir.absolute()}") return True # 3. 如果cx_Freeze失败,尝试PyInstaller print("\n❌ cx_Freeze构建失败,尝试PyInstaller...") deep_cleanup() # 再次清理 if try_pyinstaller_fallback(): print("\n✅ PyInstaller构建成功!") print("📁 文件位置: dist/") return True print("\n❌ 所有构建方法都失败了") print("建议手动检查依赖和环境配置") return False if __name__ == "__main__": success = main() if not success: print("失败")