SlideCombine/build_exe.py
2025-11-24 17:24:27 +08:00

387 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PDF书签合并工具 - 自动打包脚本
使用PyInstaller将Python程序打包成独立的exe文件
"""
import os
import sys
import subprocess
import shutil
from pathlib import Path
def check_pyinstaller():
"""检查是否安装了PyInstaller"""
try:
subprocess.run([sys.executable, "-c", "import PyInstaller"],
check=True, capture_output=True)
print("✅ PyInstaller 已安装")
return True
except subprocess.CalledProcessError:
print("❌ PyInstaller 未安装")
return False
def install_pyinstaller():
"""安装PyInstaller"""
print("正在安装 PyInstaller...")
try:
subprocess.run([sys.executable, "-m", "pip", "install", "pyinstaller"],
check=True)
print("✅ PyInstaller 安装成功")
return True
except subprocess.CalledProcessError as ex:
print(f"❌ PyInstaller 安装失败: {ex}")
return False
def clean_build():
"""清理之前的构建"""
print("🧹 清理之前的构建...")
folders_to_remove = ['build', 'dist', '__pycache__']
files_to_remove = ['SlideCombine.spec']
for folder in folders_to_remove:
if os.path.exists(folder):
shutil.rmtree(folder)
print(f" 已删除文件夹: {folder}")
for file in files_to_remove:
if os.path.exists(file):
os.remove(file)
print(f" 已删除文件: {file}")
def create_spec_file():
"""创建PyInstaller配置文件"""
spec_content = '''
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['slide_combine.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
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='SlideCombine',
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,
icon='app.ico', # 图标文件(如果存在)
version='version_info.txt' # 版本信息(如果存在)
)
'''
with open('SlideCombine.spec', 'w', encoding='utf-8') as f:
f.write(spec_content)
print("✅ 已创建 SlideCombine.spec 配置文件")
def create_version_info():
"""创建版本信息文件"""
version_info = '''
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(2,0,0,0),
prodvers=(2,0,0,0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
flags=0x0,
# The operating system for which this file was designed.
# 0x4 - NT and there is no need to change it.
OS=0x4,
# The general type of file.
# 0x1 - the file is an application.
fileType=0x1,
# The function of the file.
# 0x0 - the function is not defined for this fileType
subtype=0x0,
# Creation date and time stamp.
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
u'080404B0',
[StringStruct(u'CompanyName', u'PDF书签合并工具'),
StringStruct(u'FileDescription', u'PDF书签合并工具 - 用于从PDF文件夹中提取书签信息与TXT元数据文件合并'),
StringStruct(u'FileVersion', u'2.0.0.0'),
StringStruct(u'InternalName', u'SlideCombine'),
StringStruct(u'LegalCopyright', u'Copyright (C) 2024'),
StringStruct(u'OriginalFilename', u'SlideCombine.exe'),
StringStruct(u'ProductName', u'PDF书签合并工具'),
StringStruct(u'ProductVersion', u'2.0.0.0')])
]),
VarFileInfo([VarStruct(u'Translation', [2052, 1200])])
]
)
'''
with open('version_info.txt', 'w', encoding='utf-8') as f:
f.write(version_info)
print("✅ 已创建 version_info.txt 版本信息文件")
def build_exe():
"""构建exe文件"""
print("🔨 开始构建 exe 文件...")
try:
# 构建命令
cmd = [
sys.executable, '-m', 'PyInstaller',
'--clean',
'--onefile',
'--windowed',
'--name=SlideCombine',
'slide_combine.py'
]
# 如果有图标文件,添加图标参数
if os.path.exists('app.ico'):
cmd.insert(-1, '--icon=app.ico')
print("✅ 已找到图标文件: app.ico")
else:
print("⚠️ 未找到图标文件,将使用默认图标")
print(f"执行命令: {' '.join(cmd)}")
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
print("✅ 构建成功!")
return True
except subprocess.CalledProcessError as ex:
print(f"❌ 构建失败: {ex}")
if ex.stderr:
print(f"错误信息: {ex.stderr}")
return False
def create_release_package():
"""创建发布包"""
print("📦 创建发布包...")
# 检查dist文件夹
dist_path = Path('dist')
if not dist_path.exists():
print("❌ 未找到 dist 文件夹")
return False
# 查找生成的exe文件
exe_files = list(dist_path.glob('*.exe'))
if not exe_files:
print("❌ 未找到生成的 exe 文件")
return False
exe_file = exe_files[0]
print(f"✅ 找到 exe 文件: {exe_file}")
# 创建发布包文件夹
import datetime
version = "2.0.0"
date = datetime.datetime.now().strftime("%Y%m%d")
package_name = f"SlideCombine_v{version}_{date}"
package_path = Path(package_name)
if package_path.exists():
shutil.rmtree(package_path)
package_path.mkdir()
print(f"✅ 创建发布包文件夹: {package_name}")
# 复制exe文件
shutil.copy2(exe_file, package_path / 'SlideCombine.exe')
print("✅ 复制主程序文件")
# 创建使用说明
readme_content = f"""PDF书签合并工具 v{version} 使用说明
=====================================
系统要求:
- Windows 7 SP1 或更高版本
- 无需额外安装软件(绿色软件)
使用方法:
1. 双击运行 SlideCombine.exe
2. 选择三个路径:
- PDF文件夹路径包含 FreePic2Pdf_bkmk.txt 文件的文件夹
- TXT源文件路径包含元数据 TXT 文件的路径
- 输出路径:合并后文件的保存位置
3. 点击"开始合并"按钮
4. 等待处理完成
示例目录结构:
PDF文件夹/
├─ CH-875 1-3/FreePic2Pdf_bkmk.txt
├─ CH-875 4-6/FreePic2Pdf_bkmk.txt
TXT源文件/
├─ CH-875 1-3.txt
├─ CH-875 4-6.txt
输出结果:
输出路径/CH-875.txt (合并后的文件)
特点:
- 🚀 运行速度快
- 📦 绿色软件,无需安装
- 🎯 智能文件分组
- 📊 详细处理日志
- 🌍 支持多种文件编码
- 💾 独立程序,无依赖
故障排除:
- 如果程序无法启动,请检查是否有杀毒软件阻止运行
- 确保输入的路径存在且有访问权限
- 查看日志输出了解详细的处理信息
版本信息:
- 程序版本v{version}
- 构建日期:{date}
- 开发语言Python
- 界面框架Tkinter
技术支持:
这是一个绿色软件,解压即用,无需安装任何依赖项。
"""
with open(package_path / '使用说明.txt', 'w', encoding='utf-8') as f:
f.write(readme_content)
print("✅ 创建使用说明")
# 创建启动脚本
bat_content = '''@echo off
title PDF书签合并工具 v2.0
echo 启动 PDF书签合并工具...
echo.
if exist "SlideCombine.exe" (
start "" "SlideCombine.exe"
echo ✅ 程序已启动
) else (
echo ❌ 错误:未找到 SlideCombine.exe
echo 请确保在正确的目录中运行此脚本
pause
)
timeout /t 2 >nul
'''
with open(package_path / '启动程序.bat', 'w', encoding='gbk') as f:
f.write(bat_content)
print("✅ 创建启动脚本")
# 获取文件大小
exe_size = (package_path / 'SlideCombine.exe').stat().st_size
size_mb = exe_size / (1024 * 1024)
size_kb = exe_size / 1024
print(f"""
✅ 发布包创建完成!
📁 发布包位置: {package_path.absolute()}
💾 主程序大小: {size_kb:.1f} KB ({size_mb:.1f} MB)
📋 包含内容:
├─ SlideCombine.exe (主程序)
├─ 使用说明.txt (用户指南)
└─ 启动程序.bat (快捷启动)
🎉 部署说明:
1. 将整个 {package_name} 文件夹复制到目标电脑
2. 双击"启动程序.bat"或直接运行"SlideCombine.exe"
3. 无需安装任何软件,绿色环保
""")
return True
def main():
"""主函数"""
print("="*50)
print(" PDF书签合并工具 - 自动打包脚本")
print("="*50)
print()
# 检查Python版本
if sys.version_info < (3, 7):
print("❌ 需要 Python 3.7 或更高版本")
sys.exit(1)
print(f"✅ Python版本: {sys.version}")
# 检查主程序文件
if not os.path.exists('slide_combine.py'):
print("❌ 未找到 slide_combine.py 文件")
print("请确保在项目根目录下运行此脚本")
sys.exit(1)
# 检查/安装PyInstaller
if not check_pyinstaller():
print("尝试自动安装 PyInstaller...")
if not install_pyinstaller():
print("请手动安装 PyInstaller: pip install pyinstaller")
sys.exit(1)
# 清理之前的构建
clean_build()
# 创建配置文件
create_spec_file()
create_version_info()
# 构建exe文件
if not build_exe():
print("❌ 构建失败,请检查错误信息")
sys.exit(1)
# 创建发布包
if not create_release_package():
print("❌ 创建发布包失败")
sys.exit(1)
print("🎉 打包完成!")
if __name__ == "__main__":
main()