|
|
#!/usr/bin/env python3
|
|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
MagicWord 1.0.0 版本发布脚本
|
|
|
用于构建和打包应用程序,包含所有图片和图标资源
|
|
|
"""
|
|
|
|
|
|
import os
|
|
|
import sys
|
|
|
import subprocess
|
|
|
import platform
|
|
|
import shutil
|
|
|
import zipfile
|
|
|
from datetime import datetime
|
|
|
from PIL import Image
|
|
|
|
|
|
def run_command(command, shell=False, cwd=None):
|
|
|
"""运行命令并返回结果"""
|
|
|
try:
|
|
|
result = subprocess.run(command, shell=shell, capture_output=True, text=True, encoding='utf-8', cwd=cwd)
|
|
|
return result.returncode, result.stdout, result.stderr
|
|
|
except Exception as e:
|
|
|
return -1, "", str(e)
|
|
|
|
|
|
def create_ico_from_png():
|
|
|
"""从PNG图标创建ICO文件"""
|
|
|
print("创建ICO图标文件...")
|
|
|
|
|
|
# 检查是否存在256x256的PNG图标
|
|
|
png_path = "resources/icons/app_icon_256X256.png"
|
|
|
ico_path = "resources/icons/app_icon.ico"
|
|
|
|
|
|
if os.path.exists(png_path):
|
|
|
try:
|
|
|
# 打开PNG图像
|
|
|
img = Image.open(png_path)
|
|
|
|
|
|
# 创建不同尺寸的图标
|
|
|
icon_sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
|
|
|
|
|
|
# 保存为ICO格式
|
|
|
img.save(ico_path, format='ICO', sizes=icon_sizes)
|
|
|
print(f"ICO图标创建成功: {ico_path}")
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
print(f"创建ICO图标失败: {e}")
|
|
|
return False
|
|
|
else:
|
|
|
print(f"找不到PNG图标文件: {png_path}")
|
|
|
return False
|
|
|
|
|
|
def clean_build_dirs():
|
|
|
"""清理构建目录"""
|
|
|
print("清理构建目录...")
|
|
|
dirs_to_clean = ['build', 'dist', '__pycache__', '*.egg-info']
|
|
|
|
|
|
for dir_name in dirs_to_clean:
|
|
|
if '*' in dir_name:
|
|
|
# 处理通配符
|
|
|
import glob
|
|
|
for path in glob.glob(dir_name):
|
|
|
if os.path.isdir(path):
|
|
|
shutil.rmtree(path, ignore_errors=True)
|
|
|
elif os.path.exists(dir_name):
|
|
|
if os.path.isdir(dir_name):
|
|
|
shutil.rmtree(dir_name, ignore_errors=True)
|
|
|
else:
|
|
|
os.remove(dir_name)
|
|
|
|
|
|
# 清理src目录下的__pycache__
|
|
|
for root, dirs, files in os.walk('src'):
|
|
|
for dir_name in dirs:
|
|
|
if dir_name == '__pycache__':
|
|
|
cache_path = os.path.join(root, dir_name)
|
|
|
shutil.rmtree(cache_path, ignore_errors=True)
|
|
|
print(f"清理缓存: {cache_path}")
|
|
|
|
|
|
def install_dependencies():
|
|
|
"""安装依赖"""
|
|
|
print("安装项目依赖...")
|
|
|
|
|
|
# 首先安装PIL(用于图标转换)
|
|
|
code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "Pillow"])
|
|
|
if code != 0:
|
|
|
print(f"Pillow安装失败: {stderr}")
|
|
|
return False
|
|
|
|
|
|
# 安装其他依赖
|
|
|
code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"])
|
|
|
if code != 0:
|
|
|
print(f"依赖安装失败: {stderr}")
|
|
|
return False
|
|
|
print("依赖安装成功")
|
|
|
return True
|
|
|
|
|
|
def build_executable():
|
|
|
"""构建可执行文件"""
|
|
|
print("构建可执行文件...")
|
|
|
|
|
|
# 安装pyinstaller
|
|
|
print("安装PyInstaller...")
|
|
|
code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "pyinstaller"])
|
|
|
if code != 0:
|
|
|
print(f"PyInstaller安装失败: {stderr}")
|
|
|
return False
|
|
|
|
|
|
# 创建ICO图标
|
|
|
create_ico_from_png()
|
|
|
|
|
|
# PyInstaller命令 - 完整版本
|
|
|
pyinstaller_cmd = [
|
|
|
"pyinstaller",
|
|
|
"--name", "MagicWord",
|
|
|
"--version", "1.0.0", # 设置版本号为1.0.0
|
|
|
"--distpath", "dist",
|
|
|
"--workpath", "build",
|
|
|
"--specpath", ".",
|
|
|
# 添加资源文件
|
|
|
"--add-data", "resources;resources",
|
|
|
"--add-data", "resources/icons;resources/icons",
|
|
|
"--add-data", "resources/config;resources/config",
|
|
|
"--add-data", "resources/qss;resources/qss",
|
|
|
"--add-data", "src;src",
|
|
|
"--add-data", "src/ui;src/ui",
|
|
|
"--add-data", "src/demo;src/demo",
|
|
|
# 隐藏导入
|
|
|
"--hidden-import", "PyQt5",
|
|
|
"--hidden-import", "PyQt5.QtCore",
|
|
|
"--hidden-import", "PyQt5.QtGui",
|
|
|
"--hidden-import", "PyQt5.QtWidgets",
|
|
|
"--hidden-import", "requests",
|
|
|
"--hidden-import", "beautifulsoup4",
|
|
|
"--hidden-import", "python-docx",
|
|
|
"--hidden-import", "PyPDF2",
|
|
|
"--hidden-import", "ebooklib",
|
|
|
"--hidden-import", "chardet",
|
|
|
"--hidden-import", "PIL",
|
|
|
"--hidden-import", "pillow",
|
|
|
# 图标设置
|
|
|
"--icon", "resources/icons/app_icon.ico" if os.path.exists("resources/icons/app_icon.ico") else "resources/icons/app_icon_256X256.png",
|
|
|
"--windowed", # 无控制台窗口
|
|
|
"--noconfirm",
|
|
|
"--clean", # 清理临时文件
|
|
|
"src/main.py"
|
|
|
]
|
|
|
|
|
|
print("运行PyInstaller...")
|
|
|
code, stdout, stderr = run_command(pyinstaller_cmd)
|
|
|
|
|
|
if code != 0:
|
|
|
print(f"完整构建失败,尝试简化构建: {stderr}")
|
|
|
# 简化版本
|
|
|
simple_cmd = [
|
|
|
"pyinstaller",
|
|
|
"--onefile",
|
|
|
"--windowed",
|
|
|
"--icon=resources/icons/app_icon.ico" if os.path.exists("resources/icons/app_icon.ico") else "resources/icons/app_icon_256X256.png",
|
|
|
"--add-data=resources;resources",
|
|
|
"--add-data=resources/icons;resources/icons",
|
|
|
"--add-data=src;src",
|
|
|
"--name=MagicWord",
|
|
|
"--version=1.0.0",
|
|
|
"--clean",
|
|
|
"src/main.py"
|
|
|
]
|
|
|
code, stdout, stderr = run_command(simple_cmd)
|
|
|
if code != 0:
|
|
|
print(f"简化构建也失败: {stderr}")
|
|
|
return False
|
|
|
|
|
|
print("可执行文件构建成功")
|
|
|
return True
|
|
|
|
|
|
def create_package():
|
|
|
"""创建发布包"""
|
|
|
print("创建发布包...")
|
|
|
|
|
|
# 检查构建结果
|
|
|
if platform.system() == "Windows":
|
|
|
exe_path = "dist/MagicWord.exe"
|
|
|
else:
|
|
|
exe_path = "dist/MagicWord"
|
|
|
|
|
|
if not os.path.exists(exe_path):
|
|
|
print(f"错误: 找不到可执行文件 {exe_path}")
|
|
|
return False
|
|
|
|
|
|
# 创建发布目录
|
|
|
release_dir = "dist_package_v1.0"
|
|
|
if os.path.exists(release_dir):
|
|
|
shutil.rmtree(release_dir)
|
|
|
os.makedirs(release_dir)
|
|
|
|
|
|
# 复制文件到发布目录
|
|
|
files_to_copy = [
|
|
|
(exe_path, "MagicWord.exe" if platform.system() == "Windows" else "MagicWord"),
|
|
|
("README.md", "README.md"),
|
|
|
("CHANGELOG.md", "CHANGELOG.md"),
|
|
|
("requirements.txt", "requirements.txt"),
|
|
|
("install_and_fix.py", "install_and_fix.py"),
|
|
|
]
|
|
|
|
|
|
for src, dst in files_to_copy:
|
|
|
if os.path.exists(src):
|
|
|
shutil.copy2(src, os.path.join(release_dir, dst))
|
|
|
print(f"复制: {src} -> {dst}")
|
|
|
|
|
|
# 复制图标文件到发布包
|
|
|
icons_dir = os.path.join(release_dir, "icons")
|
|
|
if os.path.exists("resources/icons"):
|
|
|
shutil.copytree("resources/icons", icons_dir)
|
|
|
print("复制图标文件到发布包")
|
|
|
|
|
|
# 创建运行脚本
|
|
|
if platform.system() == "Windows":
|
|
|
run_script = """@echo off
|
|
|
echo MagicWord 1.0.0 启动中...
|
|
|
cd /d "%~dp0"
|
|
|
start MagicWord.exe
|
|
|
"""
|
|
|
with open(os.path.join(release_dir, "run.bat"), "w") as f:
|
|
|
f.write(run_script)
|
|
|
|
|
|
# 创建桌面快捷方式脚本
|
|
|
desktop_shortcut_script = """@echo off
|
|
|
echo 创建桌面快捷方式...
|
|
|
set SCRIPT_DIR=%~dp0
|
|
|
set DESKTOP=%USERPROFILE%\Desktop
|
|
|
set SHORTCUT=%DESKTOP%\MagicWord.lnk
|
|
|
powershell -Command "$WshShell = New-Object -comObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut('%SHORTCUT%'); $Shortcut.TargetPath = '%SCRIPT_DIR%MagicWord.exe'; $Shortcut.WorkingDirectory = '%SCRIPT_DIR%'; $Shortcut.IconLocation = '%SCRIPT_DIR%icons\\app_icon_256X256.png'; $Shortcut.Save()"
|
|
|
echo 桌面快捷方式创建完成!
|
|
|
pause
|
|
|
"""
|
|
|
with open(os.path.join(release_dir, "create_desktop_shortcut.bat"), "w") as f:
|
|
|
f.write(desktop_shortcut_script)
|
|
|
|
|
|
else:
|
|
|
run_script = """#!/bin/bash
|
|
|
echo "MagicWord 1.0.0 启动中..."
|
|
|
cd "$(dirname "$0")"
|
|
|
./MagicWord &
|
|
|
"""
|
|
|
with open(os.path.join(release_dir, "run.sh"), "w") as f:
|
|
|
f.write(run_script)
|
|
|
os.chmod(os.path.join(release_dir, "run.sh"), 0o755)
|
|
|
|
|
|
# 创建发布说明
|
|
|
release_info = f"""MagicWord 1.0.0 发布包
|
|
|
构建时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
|
平台: {platform.system()} {platform.machine()}
|
|
|
Python版本: {platform.python_version()}
|
|
|
|
|
|
快速开始:
|
|
|
1. 运行 install_and_fix.py 安装依赖(如果需要)
|
|
|
2. 运行 run.bat (Windows) 或 run.sh (Linux/Mac)
|
|
|
3. 或直接运行 MagicWord.exe
|
|
|
|
|
|
功能特性:
|
|
|
- 完整的文档处理功能
|
|
|
- 打字练习模式
|
|
|
- 学习模式
|
|
|
- 多种文档格式支持(Word, PDF, TXT等)
|
|
|
- 美观的Word风格界面
|
|
|
- 完整的图标和界面资源
|
|
|
|
|
|
图标说明:
|
|
|
- 包含完整的图标资源文件
|
|
|
- 支持多种尺寸的图标(32x32, 64x64, 128x128, 256x256)
|
|
|
- Windows版本包含ICO格式图标
|
|
|
- 可创建桌面快捷方式
|
|
|
|
|
|
详细更新请查看 CHANGELOG.md
|
|
|
"""
|
|
|
|
|
|
with open(os.path.join(release_dir, "发布说明.txt"), "w", encoding='utf-8') as f:
|
|
|
f.write(release_info)
|
|
|
|
|
|
# 创建ZIP压缩包
|
|
|
print("创建ZIP压缩包...")
|
|
|
zip_filename = f"MagicWord_v1.0.0_{platform.system()}_{platform.machine()}"
|
|
|
with zipfile.ZipFile(f"{zip_filename}.zip", 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
|
for root, dirs, files in os.walk(release_dir):
|
|
|
for file in files:
|
|
|
file_path = os.path.join(root, file)
|
|
|
arc_path = os.path.relpath(file_path, release_dir)
|
|
|
zipf.write(file_path, arc_path)
|
|
|
print(f"添加到压缩包: {arc_path}")
|
|
|
|
|
|
print(f"发布包创建成功: {zip_filename}.zip")
|
|
|
return True
|
|
|
|
|
|
def main():
|
|
|
"""主函数"""
|
|
|
print("=" * 50)
|
|
|
print("MagicWord 1.0.0 构建脚本")
|
|
|
print("=" * 50)
|
|
|
|
|
|
# 检查Python版本
|
|
|
if sys.version_info < (3, 6):
|
|
|
print("错误: 需要Python 3.6或更高版本")
|
|
|
return False
|
|
|
|
|
|
# 清理构建目录
|
|
|
clean_build_dirs()
|
|
|
|
|
|
# 安装依赖
|
|
|
if not install_dependencies():
|
|
|
print("依赖安装失败")
|
|
|
return False
|
|
|
|
|
|
# 构建可执行文件
|
|
|
if not build_executable():
|
|
|
print("可执行文件构建失败")
|
|
|
return False
|
|
|
|
|
|
# 创建发布包
|
|
|
if not create_package():
|
|
|
print("发布包创建失败")
|
|
|
return False
|
|
|
|
|
|
print("=" * 50)
|
|
|
print("构建完成!")
|
|
|
print("发布包位于: dist_package_v1.0/")
|
|
|
print("ZIP压缩包已创建")
|
|
|
print("=" * 50)
|
|
|
|
|
|
return True
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
success = main()
|
|
|
sys.exit(0 if success else 1) |