1.前言
python项目的部署工作基本是属于算法的最后阶段,同样也是最容易出现问题的阶段,毕竟IDE中的运行甚至debug都是可以直接给出问题,再加上开发机器的版本较新,也很少会出现各种各样的dll系统问题。win和linux部署相比,linux由于其系统相对较为简单,部署问题较少,但windows的部署所面临的bug则千奇百怪,尤其是较为老的服务器版本。
本次问题主要是算法库版本与windows服务器不兼容导致的,开发机使用了windows11,并且算法库均为最新版本;测试人员不够专业,没有使用与生产环境相同的测试环境;直到上线前期,不兼容问题出现,搜集了各类资料,最终定位解决。
2.系统环境信息
硬件环境
- 处理器 12th Gen Intel® Core™ i5-12500H 3.10 GHz
- 机带 RAM 32.0 GB (31.7 GB 可用)
- 设备 ID B3E450C9-FC4F-4934-9ADC-C643A1484672
- 产品 ID 00342-30616-35677-AAOEM
- 系统类型 64 位操作系统, 基于 x64 的处理器
系统信息
- 版本 Windows 11 家庭中文版
- 版本号 24H2
- 安装日期 2024/12/27
- 操作系统版本 26100.2605
- 体验 Windows 功能体验包 1000.26100.36.0
生产服务器系统
- 版本win2008 R2
开发阶段算法库版本
算法库 | 版本 |
---|---|
pandas | 2.2.0 |
numpy | 1.26.4 |
lightgbm | 4.4.0 |
pyinstaller | 6.9.0 |
torch | 2.3.0 |
4.Bug排查过程
1.问题发生–dll丢失
打包程序部署后,在win2008服务器上,系统报错丢失api-ms-win-core-path-l1-1-0.dll, 这Microsoft Windows 操作系统中的一个动态链接库(DLL)文件,主要与文件路径操作和路径管理相关。它是 Windows API(应用程序编程接口)的一部分,提供了一些核心功能,帮助 Windows 应用程序在操作系统中进行路径相关的操作。
2.dll丢失问题解决
在DLL下载网站上下载这个库,分别放入C:\Windows\System32和C:\Windows\SysWOW64目录下,问题解决。此时运行框能够正常显示出来,表明dll确实问题已经解决,问题到这,都算是很简单的事件。
3.模型调用报错
紧接着,需要进行接口测试,传参后,程序报错,内容大致如下:
0SError:[winError193]x1 不是有效的 Win32 应用程序。
Failed to load \lightghm\win\lib.Lightgbm.dll’. Most likely this dynlib/dll was not found when the applicat ion wfrozen
4.Pyinstaller降版本
最显眼的winError193故障报错,第一时间对此进行了排查(被这个故障报错干扰了判断),很多内容答案显示可能在 64 位 Windows 系统上尝试运行一个 32 位应用程序,或者反过来。比如,尝试用 32 位的应用程序加载 64 位的动态链接库(DLL),或者使用 64 位的程序加载 32 位的 DLL,会出现这个错误。
针对这个问题,重新下载了dll文件,并且使用了dll depends工具进行了相应排查,并没有发现任何问题。怀疑是Pyinstaller问题,将其降级到3.0+版本,并且重新进行了多次打包,问题没有解决。
5.lightgbm问题排查
由于winError193故障并没有找到有效的解决方案,开始怀疑是lightgbm的版本问题导致,并对此进行了相应的搜索,发现存在此类相关可能,经搜索,lightgbm可能不完全支持 Windows 2008 及其早期版本,这将会导致兼容性问题。
6.lightgbm降版本
经过搜集,针对windows2008的支持情况,选择了2.2.3版本的lightgbm,为了快速验证,构建了一个小项目进行打包测试,使用了lightgbm和torch,代码如下:
import numpy as np
import lightgbm as lgb
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score# 1. 使用 LightGBM 进行分类任务
# 创建一个简单的二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 将数据转换为 LightGBM Dataset 格式
train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)# 设置 LightGBM 超参数
params = {'objective': 'binary','metric': 'binary_error','boosting_type': 'gbdt','num_leaves': 31,'learning_rate': 0.05,'feature_fraction': 0.9,
}# 训练 LightGBM 模型
lgb_model = lgb.train(params, train_data, valid_sets=[test_data], num_boost_round=100)# 使用 LightGBM 模型进行预测
y_pred_lgb = lgb_model.predict(X_test)
y_pred_lgb = (y_pred_lgb > 0.5).astype(int)# 评估 LightGBM 模型的准确度
accuracy_lgb = accuracy_score(y_test, y_pred_lgb)
print(f"LightGBM 分类模型准确率: {accuracy_lgb:.4f}")# 2. 使用 PyTorch 构建神经网络进行回归任务
# 创建一个简单的回归数据集
X_reg, y_reg = make_classification(n_samples=1000, n_features=20, n_informative=5, n_classes=2, random_state=42)# 划分训练集和测试集
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(X_reg, y_reg, test_size=0.2, random_state=42)# 将数据转换为 PyTorch Tensor
X_train_tensor = torch.tensor(X_train_reg, dtype=torch.float32)
y_train_tensor = torch.tensor(y_train_reg, dtype=torch.float32).view(-1, 1)
X_test_tensor = torch.tensor(X_test_reg, dtype=torch.float32)
y_test_tensor = torch.tensor(y_test_reg, dtype=torch.float32).view(-1, 1)# 定义一个简单的神经网络
class SimpleNN(nn.Module):def __init__(self):super(SimpleNN, self).__init__()self.fc1 = nn.Linear(20, 64)self.fc2 = nn.Linear(64, 32)self.fc3 = nn.Linear(32, 1)def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x# 初始化模型,定义损失函数和优化器
model = SimpleNN()
criterion = nn.MSELoss() # 由于是回归任务,使用均方误差损失
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练神经网络模型
epochs = 100
for epoch in range(epochs):model.train()optimizer.zero_grad()outputs = model(X_train_tensor)loss = criterion(outputs, y_train_tensor)loss.backward()optimizer.step()if (epoch + 1) % 10 == 0:print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")# 使用神经网络模型进行预测
model.eval()
with torch.no_grad():y_pred_nn = model(X_test_tensor)# 计算模型的均方误差
mse = criterion(y_pred_nn, y_test_tensor)
print(f"神经网络回归模型均方误差: {mse.item():.4f}")
打包测试后发现,2.2.3版本的lightgbm能够正常运行在win2008上,说明lightgbm降版本可以解决当前的系统报错问题。
7.问题解决
lightgbm进行降版本,使用2.2.3版本,重新打包后,发到win2008的测试环境中测试,正常运行,正常建模,问题得到解决。
5.总结
1算法库版本与系统兼容性问题
- 在项目的部署过程中,算法库版本与生产环境的系统兼容性问题是常见的挑战。特别是在Windows 2008 R2服务器上部署现代算法库时,由于操作系统较旧且不再接收微软的更新,很多新的库和API可能无法正常工作。
- 例如,在此次部署中,开发环境中使用了较新的算法库版本(如lightgbm 4.4.0),而在Windows 2008服务器上,这些库可能存在兼容性问题,导致程序运行时出现报错(如dll丢失)。在这种情况下,选择适配服务器环境的较旧版本的算法库(如lightgbm 2.2.3)往往能够解决问题。
- 在进行生产环境部署时,确保开发环境与生产环境的一致性,包括操作系统和算法库版本的兼容性,对于顺利部署和避免不必要的技术障碍至关重要。
2.PyInstaller与系统环境的配合
- PyInstaller作为一个将Python程序打包为可执行文件的工具,尽管在现代开发环境中表现良好,但在老旧的操作系统上可能会遇到意外的兼容性问题。
- 在此次案例中,虽然PyInstaller被用于打包Python程序,但由于系统环境较为陈旧,导致报错(如winError193),这通常是因为32位与64位架构的不兼容所引起的。降级PyInstaller版本(如3.0+版本)并重新打包,未能直接解决问题。通过进一步排查发现,问题的根源在于使用的lightgbm版本与Windows 2008的兼容性。
- 在使用PyInstaller打包程序时,除了关注打包本身的设置外,还需要特别考虑目标服务器的操作系统版本及其支持的Python库版本,以确保打包后的程序能够在目标环境中正常运行。