修改打包交脚本

This commit is contained in:
yovinchen 2025-07-02 19:37:10 +08:00
parent 02341150a9
commit c0568cc1ec
3 changed files with 308 additions and 30 deletions

85
BUILD_FIXES.md Normal file
View File

@ -0,0 +1,85 @@
# Windows构建问题修复指南
## 🔧 已修复的问题
### 1. Hidden import 'numpy.core._methods' not found
**解决方案**: 在spec文件中添加了完整的numpy隐藏导入
```python
'numpy.core._methods',
'numpy.core._dtype_ctypes',
'numpy.core._internal',
```
### 2. Hidden import "jinja2" not found
**解决方案**: 添加了jinja2相关导入
```python
'jinja2',
'jinja2.ext',
'markupsafe',
```
### 3. Library not found: msvcp140-1a0962f2a91a74c6d7136a768987a591.dll
**解决方案**:
- 禁用UPX压缩 (`upx=False`)
- 添加pandas完整依赖收集
- 使用`--collect-all=pandas`选项
## 🚀 使用修复后的构建脚本
### 1. 测试环境
```bash
python test_build.py
```
### 2. 运行构建
```bash
python windows_build.py
```
## 📋 构建选项说明
### PyInstaller命令行选项
- `--clean`: 清理缓存
- `--noconfirm`: 不询问确认
- `--log-level=INFO`: 详细日志
- `--collect-all=pandas`: 收集pandas所有模块
- `--collect-all=numpy`: 收集numpy所有模块
- `--collect-all=openpyxl`: 收集openpyxl所有模块
### 关键隐藏导入
```python
'numpy.core._methods',
'pandas._libs.window.aggregations',
'ctypes.util',
'pkg_resources.py2_warn',
```
## ⚠️ 常见问题
### 1. 构建时间长
- 正常现象首次构建可能需要5-10分钟
- 后续构建会使用缓存,速度更快
### 2. 文件大小大
- 包含完整Python环境和所有依赖
- 可以通过排除不必要的模块来减小大小
### 3. 警告信息
- 大部分WARNING可以忽略
- 只要没有ERROR构建通常能成功
## 🎯 构建成功标志
```
✅ 构建成功! 耗时: XX.X秒
✅ 生成文件: dist/座位分配系统.exe
✅ 文件大小: XX.X MB
```
## 📦 分发包内容
构建成功后会生成:
- `座位分配系统_Windows_分发包/`
- `座位分配系统.exe` - 主程序
- `README.txt` - 使用说明
- `示例文件/` - 示例Excel文件如果存在

101
test_build.py Normal file
View File

@ -0,0 +1,101 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测试构建脚本 - 验证依赖和配置
"""
import sys
import subprocess
import platform
def test_dependencies():
"""测试关键依赖"""
print("=" * 50)
print("测试关键依赖")
print("=" * 50)
dependencies = [
'pandas',
'numpy',
'openpyxl',
'pyinstaller'
]
for dep in dependencies:
try:
__import__(dep)
print(f"{dep} - 已安装")
except ImportError:
print(f"{dep} - 未安装")
return False
return True
def test_hidden_imports():
"""测试隐藏导入"""
print("\n" + "=" * 50)
print("测试隐藏导入")
print("=" * 50)
hidden_imports = [
'numpy.core._methods',
'pandas._libs.window.aggregations',
'ctypes.util'
]
for imp in hidden_imports:
try:
parts = imp.split('.')
module = __import__(parts[0])
for part in parts[1:]:
module = getattr(module, part)
print(f"{imp} - 可访问")
except (ImportError, AttributeError) as e:
print(f"⚠️ {imp} - 无法访问: {e}")
return True
def test_pyinstaller():
"""测试PyInstaller"""
print("\n" + "=" * 50)
print("测试PyInstaller")
print("=" * 50)
try:
result = subprocess.run([
sys.executable, '-m', 'PyInstaller', '--version'
], capture_output=True, text=True)
if result.returncode == 0:
version = result.stdout.strip()
print(f"✅ PyInstaller版本: {version}")
return True
else:
print(f"❌ PyInstaller测试失败: {result.stderr}")
return False
except Exception as e:
print(f"❌ PyInstaller测试出错: {e}")
return False
def main():
"""主函数"""
print(f"Python版本: {sys.version}")
print(f"操作系统: {platform.system()} {platform.release()}")
print(f"架构: {platform.machine()}")
success = True
success &= test_dependencies()
success &= test_hidden_imports()
success &= test_pyinstaller()
print("\n" + "=" * 50)
if success:
print("✅ 所有测试通过,可以进行构建")
else:
print("❌ 存在问题,请先解决依赖问题")
print("=" * 50)
return success
if __name__ == '__main__':
main()

View File

@ -53,38 +53,64 @@ class WindowsBuilder:
print("\n" + "=" * 60)
print("安装构建依赖")
print("=" * 60)
required_packages = [
'pandas>=1.3.0',
'openpyxl>=3.0.0',
'numpy>=1.20.0',
'pyinstaller>=4.0'
'pyinstaller>=5.0',
'pywin32>=227' # Windows特定依赖
]
for package in required_packages:
print(f"\n检查 {package}...")
package_name = package.split('>=')[0]
try:
__import__(package_name)
print(f"{package_name} 已安装")
except ImportError:
print(f"📦 安装 {package}...")
# 特殊处理pywin32
if package_name == 'pywin32':
try:
cmd = [sys.executable, '-m', 'pip', 'install', package, '--user']
result = subprocess.run(cmd, capture_output=True, text=True,
encoding='utf-8', errors='ignore')
if result.returncode == 0:
print(f"{package} 安装成功")
else:
print(f"{package} 安装失败")
print(f"错误信息: {result.stderr}")
return False
except Exception as e:
print(f"❌ 安装过程出错: {e}")
import win32api
print(f"{package_name} 已安装")
continue
except ImportError:
pass
else:
try:
__import__(package_name)
print(f"{package_name} 已安装")
continue
except ImportError:
pass
print(f"📦 安装 {package}...")
try:
cmd = [sys.executable, '-m', 'pip', 'install', package, '--upgrade']
result = subprocess.run(cmd, capture_output=True, text=True,
encoding='utf-8', errors='ignore')
if result.returncode == 0:
print(f"{package} 安装成功")
else:
print(f"{package} 安装失败")
print(f"错误信息: {result.stderr}")
# 对于pywin32尝试替代安装方法
if package_name == 'pywin32':
print("尝试使用conda安装pywin32...")
try:
cmd_conda = ['conda', 'install', '-y', 'pywin32']
result_conda = subprocess.run(cmd_conda, capture_output=True, text=True)
if result_conda.returncode == 0:
print("✅ pywin32 通过conda安装成功")
continue
except:
pass
print("⚠️ pywin32安装失败但可能不影响构建")
continue
return False
except Exception as e:
print(f"❌ 安装过程出错: {e}")
return False
return True
def clean_build_dirs(self):
@ -128,7 +154,7 @@ a = Analysis(
hiddenimports=[
# 核心依赖
'pandas',
'openpyxl',
'openpyxl',
'numpy',
'xlsxwriter',
'xlrd',
@ -138,7 +164,7 @@ a = Analysis(
'platform',
'sys',
'os',
# openpyxl相关
'openpyxl.workbook',
'openpyxl.worksheet',
@ -148,30 +174,59 @@ a = Analysis(
'openpyxl.reader.excel',
'openpyxl.cell',
'openpyxl.formatting',
# pandas相关
'pandas.io.excel',
'pandas.io.common',
'pandas.io.parsers',
'pandas.io.formats.excel',
'pandas._libs',
'pandas._libs.tslibs',
'pandas._libs.tslibs.base',
'pandas._libs.tslibs.timedeltas',
'pandas._libs.tslibs.np_datetime',
'pandas._libs.tslibs.nattype',
'pandas._libs.window',
'pandas._libs.window.aggregations',
'pandas._libs.hashtable',
'pandas._libs.algos',
'pandas._libs.index',
# numpy相关
'numpy.core',
'numpy.core.multiarray',
'numpy.core.umath',
'numpy.core._methods',
'numpy.core._dtype_ctypes',
'numpy.core._internal',
'numpy.lib.format',
'numpy.random',
'numpy.random._pickle',
# 编码相关
'encodings',
'encodings.utf_8',
'encodings.gbk',
'encodings.cp1252',
'encodings.latin1',
# 其他必要模块
'_ctypes',
'ctypes.util'
'ctypes.util',
'pkg_resources',
'pkg_resources.py2_warn',
'pkg_resources.markers',
# Jinja2相关可能被某些依赖使用
'jinja2',
'jinja2.ext',
'markupsafe',
# Windows特定模块仅在Windows上可用
# 'win32api',
# 'win32con',
# 'pywintypes',
# 'pythoncom'
],
hookspath=[],
hooksconfig={},
@ -179,7 +234,11 @@ a = Analysis(
excludes=[
# 排除不必要的大型库
'matplotlib',
'matplotlib.pyplot',
'scipy',
'sklearn',
'tensorflow',
'torch',
'IPython',
'jupyter',
'notebook',
@ -188,12 +247,37 @@ a = Analysis(
'PyQt6',
'PySide2',
'PySide6',
'PIL',
'cv2',
'seaborn',
'plotly',
'bokeh',
# 测试和开发工具
'test',
'tests',
'unittest',
'pytest',
'setuptools',
'pip',
'wheel'
'wheel',
'distutils',
# 文档和示例
'sphinx',
'docutils',
'examples',
'sample',
# 其他不需要的模块
'curses',
'readline',
'sqlite3',
'xml.etree.ElementTree',
'html',
'http',
'urllib3',
'requests'
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
@ -244,6 +328,14 @@ exe = EXE(
sys.executable, '-m', 'PyInstaller',
'--clean',
'--noconfirm',
'--log-level=INFO',
'--collect-all=pandas',
'--collect-all=numpy',
'--collect-all=openpyxl',
'--hidden-import=numpy.core._methods',
'--hidden-import=pandas._libs.window.aggregations',
'--hidden-import=ctypes.util',
'--hidden-import=pkg_resources.py2_warn',
str(spec_file)
]