修改打包交脚本
This commit is contained in:
parent
8a103224b5
commit
1e9925a9f2
42
fix_dll_build.bat
Normal file
42
fix_dll_build.bat
Normal 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
302
fix_dll_build.py
Normal 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
169
test_pandas_dll.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user