当前位置:   article > 正文

一文解决,anaconda创建虚拟环境,python模型打包,c++程序调用py文件,调用程序编写全流程。_创建一个虚拟环境并运行程序

创建一个虚拟环境并运行程序

前言

        Python是一种更适用于数据分析与计算的一种语言,在软件开发方面,尤其是界面开发可能稍有欠缺,QT是一种跨平台的C++图形用户界面程序开发框架,在VS开发工具中可以集成QT,直接在VS中进行界面开发,程序编写。最近的研究同时使用到Python和C++两种语言,因此,接口互通至关重要。以下将详细介绍C++程序调用Python模型的各个流程。

注:Python模型建立主要使用的是Anaconda中的jupyter notebook模块编写(python37版本),VS使用2015版本,QT也是2015版本。

正文

        由于在使用python时可能需要下载很多功能模块包,而且再使用C++调用这些模型时,并不一定需那么多的安装包,因此,在进行打包之前最好的方法就是创建一个新的虚拟环境(并且这个环境可以根据需要创建不同版本,因为python程序在每个版本间不兼容,需要重新将程序在创建好的虚拟环境里重新运行一遍,在运行时需要哪个包直接安装即可,此时虚拟环境中就会只有我们需要的安装包,大大减少了打包的内存)。接下来就是在虚拟环境中打包,编写py文件,然后使用c++程序调用等步骤,具体实现方法接下来一一介绍

01-创建虚拟环境

查询虚拟环境

        我这里使用的是Anaconda3,python版本使用的是3.9版本,首先这里可以通过             conda inof --envs命令   查询已经安装的虚拟环境,因为我的Anaconda安装在D盘,因此习惯先切换到D盘进行查询。执行命令之后,可以得到已安装的虚拟环境,其中带*号的表示当前虚拟环境

注:下方输入命令的界面为Anaconda Prompt (安装Anaconda3之后,会有一个这样的程序)

创建虚拟环境

        在命令行输入  conda create --name py3 python=3.7 命令即可,我这边将虚拟环境命名为py3,当显示创建完成之后,就可以在安装的Anaconda的envs文件下查询到已经创建的虚拟环境

切换虚拟环境

        当创建之后,直接通过Anaconda Prompt程序输入Jupyter Notebook之后,在选择环境那里并没有自己创建的环境,需要进行环境激活,输入conda activate py3可以切换到所创建环境,如下图所示,可以看出当前虚拟环境已经变成py3。

        接着,在当前环境下,使用 conda install ipykernel 安装程序包,然后再输入                     python -m ipykernel install --name py3  命令即可完成激活。再次使用Jupyter Notebook打开时便可以选择所需的虚拟环境。

        至此,完成虚拟环境创建任务。

02-Python模型导出和使用

导出模型

        因为在使用C++程序调用之前,是需要先将模型建立完毕的,也就是模型已经训练好的,因此,我们没有必要在需要调用的.py文件中继续将模型训练,只需要通过下面的命令导出pkl文件即可,这就是已经训练好的模型,等需要的时候,在.py文件中导入。执行下方代码。便可得到.pkl模型文件

  1. import joblib # 导入包
  2. # 划分数据集
  3. X_train, X_test, y_train, y_test = train_test_split(X,y1,test_size=0.3,random_state=2023)
  4. # 训练数据
  5. gbdt = GradientBoostingRegressor(learning_rate=0.0409, max_depth=4, n_estimators=500, random_state=2023)
  6. # 拟合数据
  7. gbdt.fit(X_train,y_train)
  8. # 导出模型pkl文件
  9. joblib.dump(gbdt,'../pkl/Pred.pkl')
使用模型

        下面是模型的使用方法,由于现在的.pkl文件已经是训练好的模型,因此可以直接导入数据用于计算。方法如下方代码所示。执行代码之后,得到的y_pred就是经过训练后的YP_Pred_102.pkl模型文件的预测结果,使用非常方便。

  1. import joblib # 导入包
  2. # 获取文件
  3. pkl_file = '../pkl/Pred.pkl'
  4. # 下载模型
  5. gbdt=joblib.load(pkl_file)
  6. # 进行预测,其中X_pred代表待预测的数据集
  7. y_pred= gbdt.predict(X_pred)

03-建立py文件

        py文件就是我们用于与C++程序连接的主要文件,它既是用于python打包的的文件,又是用于在C++程序中调用的文件。这个文件里主要包含两部分内容:

        (1)、需要使用的数据包,直接导入即可(下面有程序指导)。

        (2)、定义几个需要的函数,这个函数用于在C++程序中调用,并且数据处理、pkl文件导入、模型计算,都在这个函数里实现。(程序如下所示)

        代码最上方代码 %%writefile hello_C++.py,可以将.ipynb文件转化为.py文件(因为在Anaconda中建立的python文件默认是.ipynb文件格式,后面打包需要使用.py文件)我们下方就是我们所需要py文件,该文件命名为hello_C++文件,导入所需要的包,然后还有建立的函数Pred(),当使用C++程序调用hello_C++文件后,再进行函数Pred()的调用,就可以将数据导入函数中,执行函数里的所有程序,得到计算结果。

  1. #%%writefile hello_C++.py
  2. import pandas as pd
  3. import numpy as np
  4. import math
  5. #from sklearn.externals import joblib
  6. import joblib
  7. from joblib import load
  8. import encodings
  9. import codecs
  10. import warnings
  11. import geatpy as ea
  12. warnings.filterwarnings("ignore", category=DeprecationWarning)
  13. # 这里仅是一个函数,如果还需要其他模型计算,需要建立其他函数
  14. def Pred(Paralist):
  15. X1=Paralist[0]
  16. X2=Paralist[1]
  17. X3=Paralist[2]
  18. X4 =Paralist[3]
  19. X5 =Paralist[4]
  20. ....... # 特殊原因,近展示部分代码。过程相似
  21. X_pred_dict = {'A':[X1],'B':[X2],'C':[X3],
  22. 'D':[X4],'E':[X5],...}
  23. order=[ 'A','B', 'C','D', 'E',...]
  24. X_pred=pd.DataFrame(data=X_pred_dict)
  25. X_pred=X_pred[order]
  26. X_pred=X_pred.apply(pd.to_numeric,axis=0)
  27. X_pred['A'] = pd.to_numeric(X_pred['A'],errors='coerce')
  28. X_pred['B'] = pd.to_numeric(X_pred['B'],errors='coerce')
  29. X_pred['C'] = pd.to_numeric(X_pred['C'],errors='coerce')
  30. X_pred['D'] = pd.to_numeric(X_pred['D'],errors='coerce')
  31. X_pred['E'] = pd.to_numeric(X_pred['E'],errors='coerce')
  32. ......
  33. if st_product_no== 101 :
  34. pkl_file='./pkl/Pred.pkl'
  35. ......
  36. else:
  37. pkl_file='./pkl/.pkl'
  38. gbdt=joblib.load(pkl_file)
  39. y_pred= gbdt.predict(X_pred)
  40. return y_pred

04-py文件打包

前期准备

        首先需要查看你是否已经安装支持打包的安装包pyinstaller查看方式下图所示,因为习惯于将安装包安装在D盘,先经过切换之后,再输入pyinstaller,如果和下图一样,证明已经安装程序包。否则,输入 pip install pyinstaller 进行安装即可。

文件打包

        (1)、首先将前面建立的.py文件复制之后,放到前期所建立的虚拟环境中(这里就是你需要在哪个虚拟环境打包,就放在哪个虚拟环境下),如下图所示,我这里放在虚拟环境py3中,无论哪个环境,都要放在Scripts文件下。

 

        (2)、接着进行导报,打包时,首先进入刚才放入.py文件的目录下,然后点击文件框,输入cmd命令,进入dos界面,接着输入 pyinstaller -D hello_C++.py 命令,点击回车,开始打包,时间有些长。打包完成之后,会显示打包成功。如下图所示

        (3)、打包结束之后,可以在同级目录中看到出现dist和build两个文件夹,dist文件夹中就是所需要的打包完成文件。文件中包含了很多文件,如下图所示,其中打包后dist文件夹下默认文件名为library.zip,需要改成Python37.zip(可以先复制一份,再将其改成你自己的虚拟环境的Python版本号)

        (4)、注意:前面所有的都已经打包完成,随后,需要将前面创建的py文件放入dist文件下,才能用于后期调用

使用方法

        (1)、首先将上述dist文件下的所有文件都复制下来,放入C++程序的Debug或者Release文件下,用于调试或者现场使用(主要用于没有安装Python程序的现场)

        (2)、然后,也是最重要的一点,pkl文件需要在你所需要的目录下,才能被.py文件程序调用,因此,也需要将pkl文件夹放在合适的位置

        上述步骤完成之后,剩下的就是在C++程序中进行调用py文件,调用函数等程序编写。

05-调用程序编写

路径初始化

        可以在运行时选择当前路径还是现场,两者均可使用,主要用到Py_Initialize()进行初始化。

  1. if (path_deploy == "local")
  2. {
  3. Py_SetPythonHome(L"d://Anaconda3//envs//py3");
  4. }
  5. else
  6. {
  7. Py_SetPythonHome((wchar_t*)(L"python37"));
  8. }
  9. try
  10. {
  11. Py_Initialize();//使用python之前,要调用Py_Initialize();这个函数进行初始化
  12. }
  13. catch (...)
  14. {
  15. system("pause");
  16. }
  17. if (!Py_IsInitialized())
  18. {
  19. sys_state = "Py_Initialize fail";
  20. console_WFC_thread->error("Py_Initialize失败");
  21. emit sys_state_update_link("1 Py_Initialize fail");
  22. return 0;
  23. }
  24. else
  25. {
  26. sys_state = "Py_Initialize success";
  27. console_WFC_thread->info("Py_Initialize()成功[HDGL_SYSTEM_Init]");
  28. emit sys_state_update_link("0 Py_Initialize success");
  29. }
  30. PyRun_SimpleString("import sys");
  31. PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
文件和函数调用

        使用过程的详细代码如下所示,主要用到一些API,都是写好的,直接调用即可。

  1. float test()
  2. {
  3. PyObject * pModule = NULL;// 声明变量
  4. PyObject * pFunc = NULL;// 声明变量
  5. pModule = PyImport_ImportModule("hello_C++");//这里是要调用的文件名
  6. if (pModule == NULL || PyErr_Occurred())
  7. {
  8. PyErr_Print();
  9. cout << "用户包导入错误" << endl;
  10. system("pause");
  11. }
  12. pFunc = PyObject_GetAttrString(pModule, "Pred");//这里是要调用的函数名
  13. PyObject* pLists = PyList_New(0);
  14. PyObject* pArgs = PyTuple_New(1);
  15. PyList_Append(pLists, Py_BuildValue("f", A)); // 这里传入的都是数据
  16. PyList_Append(pLists, Py_BuildValue("f", B));
  17. PyList_Append(pLists, Py_BuildValue("f", C));
  18. PyList_Append(pLists, Py_BuildValue("f", D));
  19. PyList_Append(pLists, Py_BuildValue("f", E));
  20. ......
  21. PyTuple_SetItem(pArgs, 0, pLists);
  22. PyObject* pRet = PyEval_CallObject(pFunc, pArgs);
  23. float Pred ;
  24. //获取结果
  25. PyArg_Parse(pRet, "f", &Pred);//转换返回类型
  26. return Pred;
  27. }

总结

        花了几天时间,将每个流程都详细介绍了一遍,可能每个人遇到的情况不同,具体情况具体分析,有需要的话,可以评论区讨论。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/438115
推荐阅读
相关标签
  

闽ICP备14008679号