修改打包交脚本
This commit is contained in:
parent
02341150a9
commit
c0568cc1ec
85
BUILD_FIXES.md
Normal file
85
BUILD_FIXES.md
Normal 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
101
test_build.py
Normal 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()
|
152
windows_build.py
152
windows_build.py
@ -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)
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user