修改打包交脚本

This commit is contained in:
yovinchen 2025-07-02 20:08:23 +08:00
parent 8a103224b5
commit 1e9925a9f2
3 changed files with 513 additions and 0 deletions

42
fix_dll_build.bat Normal file
View File

@ -0,0 +1,42 @@
@echo off
chcp 65001 >nul
echo ============================================================
echo pandas DLL修复构建脚本
echo 专门解决: ImportError: DLL load failed while importing aggregations
echo ============================================================
echo.
echo 检查Python环境...
python --version
if errorlevel 1 (
echo ❌ Python未安装或未添加到PATH
pause
exit /b 1
)
echo.
echo 检查pandas安装...
python -c "import pandas; print(f'✅ pandas版本: {pandas.__version__}')"
if errorlevel 1 (
echo ❌ pandas未安装
echo 正在安装pandas...
pip install pandas
)
echo.
echo 检查PyInstaller...
python -c "import PyInstaller; print('✅ PyInstaller已安装')"
if errorlevel 1 (
echo ❌ PyInstaller未安装
echo 正在安装PyInstaller...
pip install pyinstaller
)
echo.
echo 开始DLL修复构建...
python fix_dll_build.py
echo.
echo 构建完成!
echo 如果成功,可执行文件位于: dist\座位分配系统_修复版.exe
pause

302
fix_dll_build.py Normal file
View File

@ -0,0 +1,302 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
修复DLL加载失败的专用构建脚本
专门解决pandas._libs.window.aggregations DLL问题
"""
import sys
import subprocess
import platform
import site
from pathlib import Path
def get_pandas_libs_path():
"""获取pandas库文件路径"""
try:
import pandas
pandas_path = Path(pandas.__file__).parent
libs_path = pandas_path / '_libs'
return libs_path
except ImportError:
return None
def create_dll_fix_spec():
"""创建修复DLL问题的spec文件"""
# 获取pandas库路径
pandas_libs = get_pandas_libs_path()
if not pandas_libs or not pandas_libs.exists():
print("❌ 无法找到pandas库路径")
return None
print(f"✅ 找到pandas库路径: {pandas_libs}")
# 查找所有.pyd文件Windows DLL
pyd_files = list(pandas_libs.glob('**/*.pyd'))
print(f"✅ 找到 {len(pyd_files)} 个pandas DLL文件")
# 构建binaries列表
binaries_list = []
for pyd_file in pyd_files:
rel_path = pyd_file.relative_to(pandas_libs.parent)
binaries_list.append(f"(r'{pyd_file}', r'{rel_path.parent}')")
binaries_str = ',\n '.join(binaries_list)
spec_content = f'''# -*- mode: python ; coding: utf-8 -*-
# 专门修复pandas DLL加载问题的配置
import sys
from pathlib import Path
block_cipher = None
a = Analysis(
['seat_allocation_system.py'],
pathex=[],
binaries=[
# 手动包含所有pandas DLL文件
{binaries_str}
],
datas=[],
hiddenimports=[
# 核心模块
'pandas',
'numpy',
'openpyxl',
# pandas核心库必须
'pandas._libs',
'pandas._libs.lib',
'pandas._libs.hashtable',
'pandas._libs.tslib',
'pandas._libs.algos',
'pandas._libs.join',
'pandas._libs.index',
'pandas._libs.internals',
'pandas._libs.writers',
'pandas._libs.parsers',
'pandas._libs.testing',
'pandas._libs.sparse',
'pandas._libs.reduction',
'pandas._libs.ops',
'pandas._libs.missing',
'pandas._libs.groupby',
'pandas._libs.reshape',
# pandas时间序列库
'pandas._libs.tslibs',
'pandas._libs.tslibs.base',
'pandas._libs.tslibs.ccalendar',
'pandas._libs.tslibs.conversion',
'pandas._libs.tslibs.dtypes',
'pandas._libs.tslibs.fields',
'pandas._libs.tslibs.nattype',
'pandas._libs.tslibs.np_datetime',
'pandas._libs.tslibs.offsets',
'pandas._libs.tslibs.parsing',
'pandas._libs.tslibs.period',
'pandas._libs.tslibs.strptime',
'pandas._libs.tslibs.timedeltas',
'pandas._libs.tslibs.timestamps',
'pandas._libs.tslibs.timezones',
'pandas._libs.tslibs.tzconversion',
'pandas._libs.tslibs.vectorized',
# pandas窗口函数库关键
'pandas._libs.window',
'pandas._libs.window.aggregations',
'pandas._libs.window.indexers',
# numpy核心
'numpy.core._methods',
'numpy.core._dtype_ctypes',
'numpy.core.multiarray',
'numpy.core.umath',
# 其他必要模块
'ctypes.util',
'pkg_resources.py2_warn',
'encodings.utf_8',
'encodings.gbk',
# openpyxl
'openpyxl.workbook',
'openpyxl.worksheet',
'openpyxl.styles',
],
hookspath=[],
hooksconfig={{}},
runtime_hooks=[],
excludes=[
'matplotlib',
'scipy',
'IPython',
'jupyter',
'tkinter',
'PyQt5',
'PyQt6',
'PIL',
'cv2',
'sklearn',
'tensorflow',
'torch',
],
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='座位分配系统_修复版',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False, # 禁用UPX压缩避免DLL问题
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
'''
spec_file = Path('dll_fix.spec')
with open(spec_file, 'w', encoding='utf-8') as f:
f.write(spec_content)
print(f"✅ 创建DLL修复spec文件: {spec_file}")
return spec_file
def build_with_dll_fix():
"""使用DLL修复配置构建"""
print("=" * 60)
print("DLL修复构建")
print("=" * 60)
# 检查环境
if platform.system() != 'Windows':
print("❌ 此脚本仅适用于Windows")
return False
print(f"✅ 系统: {platform.system()} {platform.release()}")
# 检查主文件
main_file = Path('seat_allocation_system.py')
if not main_file.exists():
print("❌ 未找到主程序文件")
return False
# 创建修复spec文件
spec_file = create_dll_fix_spec()
if not spec_file:
return False
# 清理旧文件
dist_dir = Path('dist')
if dist_dir.exists():
import shutil
shutil.rmtree(dist_dir)
print("✅ 清理dist目录")
# 构建命令
cmd = [
sys.executable, '-m', 'PyInstaller',
'--clean',
'--noconfirm',
'--log-level=WARN', # 减少输出
str(spec_file)
]
print(f"\n执行命令: {' '.join(cmd)}")
print("开始DLL修复构建...")
try:
# 执行构建
result = subprocess.run(
cmd,
capture_output=True,
text=True,
encoding='utf-8',
errors='ignore'
)
# 显示结果
if result.returncode == 0:
print("✅ DLL修复构建成功!")
# 检查生成的文件
exe_path = Path('dist/座位分配系统_修复版.exe')
if exe_path.exists():
size_mb = exe_path.stat().st_size / (1024 * 1024)
print(f"✅ 生成文件: {exe_path}")
print(f"✅ 文件大小: {size_mb:.1f} MB")
# 测试运行
print("\n🧪 测试运行...")
test_cmd = [str(exe_path), '--help']
try:
test_result = subprocess.run(
test_cmd,
capture_output=True,
text=True,
timeout=10
)
if test_result.returncode == 0:
print("✅ 程序可以正常启动")
else:
print("⚠️ 程序启动有问题,但文件已生成")
except subprocess.TimeoutExpired:
print("⚠️ 测试超时,但文件已生成")
except Exception as e:
print(f"⚠️ 测试失败: {e}")
return True
else:
print("❌ 未找到生成的exe文件")
return False
else:
print("❌ DLL修复构建失败!")
print("错误输出:")
print(result.stderr)
return False
except Exception as e:
print(f"❌ 构建出错: {e}")
return False
def main():
"""主函数"""
print("🔧 pandas DLL加载失败修复工具")
print("专门解决: ImportError: DLL load failed while importing aggregations")
print()
success = build_with_dll_fix()
if success:
print("\n🎉 DLL修复构建完成!")
print("可执行文件: dist/座位分配系统_修复版.exe")
print("\n💡 如果仍有问题,请尝试:")
print("1. 在目标机器上安装 Visual C++ Redistributable")
print("2. 确保目标机器有相同的Windows版本")
else:
print("\n❌ DLL修复构建失败!")
print("请检查pandas安装是否完整")
input("\n按Enter键退出...")
if __name__ == '__main__':
main()

169
test_pandas_dll.py Normal file
View File

@ -0,0 +1,169 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测试pandas DLL模块加载
专门检查可能导致PyInstaller问题的模块
"""
import sys
import traceback
from pathlib import Path
def test_pandas_core():
"""测试pandas核心模块"""
print("=" * 50)
print("测试pandas核心模块")
print("=" * 50)
modules_to_test = [
'pandas',
'pandas._libs',
'pandas._libs.lib',
'pandas._libs.hashtable',
'pandas._libs.algos',
'pandas._libs.index',
'pandas._libs.writers',
'pandas._libs.parsers',
'pandas._libs.tslibs',
'pandas._libs.tslibs.base',
'pandas._libs.window',
'pandas._libs.window.aggregations', # 关键模块!
'pandas._libs.window.indexers',
]
success_count = 0
for module in modules_to_test:
try:
__import__(module)
print(f"{module}")
success_count += 1
except ImportError as e:
print(f"{module}: {e}")
except Exception as e:
print(f"⚠️ {module}: {e}")
print(f"\n成功加载: {success_count}/{len(modules_to_test)} 个模块")
return success_count == len(modules_to_test)
def test_pandas_functionality():
"""测试pandas基本功能"""
print("\n" + "=" * 50)
print("测试pandas基本功能")
print("=" * 50)
try:
import pandas as pd
import numpy as np
# 创建测试数据
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]
})
print("✅ DataFrame创建成功")
# 测试窗口函数(这是出错的关键)
result = df['A'].rolling(window=2).sum()
print("✅ rolling窗口函数正常")
# 测试聚合函数
agg_result = df.groupby('A').agg({'B': 'sum'})
print("✅ groupby聚合函数正常")
# 测试Excel读写
test_file = Path('test_pandas.xlsx')
df.to_excel(test_file, index=False)
df_read = pd.read_excel(test_file)
test_file.unlink() # 删除测试文件
print("✅ Excel读写功能正常")
return True
except Exception as e:
print(f"❌ pandas功能测试失败: {e}")
traceback.print_exc()
return False
def check_pandas_installation():
"""检查pandas安装信息"""
print("\n" + "=" * 50)
print("pandas安装信息")
print("=" * 50)
try:
import pandas as pd
print(f"✅ pandas版本: {pd.__version__}")
print(f"✅ pandas路径: {pd.__file__}")
# 检查_libs目录
pandas_path = Path(pd.__file__).parent
libs_path = pandas_path / '_libs'
if libs_path.exists():
print(f"✅ _libs目录存在: {libs_path}")
# 统计.pyd文件
pyd_files = list(libs_path.glob('**/*.pyd'))
print(f"✅ 找到 {len(pyd_files)} 个.pyd文件")
# 检查关键文件
key_files = [
'window/aggregations.cp310-win_amd64.pyd',
'window/indexers.cp310-win_amd64.pyd',
'hashtable.cp310-win_amd64.pyd',
'lib.cp310-win_amd64.pyd'
]
for key_file in key_files:
file_path = libs_path / key_file
if file_path.exists():
print(f"✅ 关键文件存在: {key_file}")
else:
print(f"❌ 关键文件缺失: {key_file}")
else:
print(f"❌ _libs目录不存在: {libs_path}")
return False
return True
except Exception as e:
print(f"❌ 检查pandas安装失败: {e}")
return False
def main():
"""主函数"""
print("🔍 pandas DLL模块测试工具")
print("用于诊断PyInstaller构建问题")
print()
# 基本信息
print(f"Python版本: {sys.version}")
print(f"平台: {sys.platform}")
# 运行测试
install_ok = check_pandas_installation()
core_ok = test_pandas_core()
func_ok = test_pandas_functionality()
print("\n" + "=" * 50)
print("测试结果总结")
print("=" * 50)
if install_ok and core_ok and func_ok:
print("✅ 所有测试通过pandas安装正常")
print("💡 如果PyInstaller仍有问题请使用 fix_dll_build.py")
else:
print("❌ 存在问题,建议:")
if not install_ok:
print(" 1. 重新安装pandas: pip uninstall pandas && pip install pandas")
if not core_ok:
print(" 2. 检查pandas C扩展是否正确编译")
if not func_ok:
print(" 3. 检查依赖库numpy等是否正常")
print("=" * 50)
input("\n按Enter键退出...")
if __name__ == '__main__':
main()