相信很多AI人写代码都是用python,但是总有迫于无奈进行C++进行编程,问就是领导想法无法揣摩,这时候就无法避免python与C++进行混合编程,相信很多伙伴能从上篇"QT C++食用教程"文章中学习到一些QT Creator使用方法以及ui界面的编程,这篇文章主要想记录一下怎么进行QT C++调用python并加载环境,希望能帮助到你!!!
1.正常直接调用python文件
直接调用python的意思是将python文件及它所需要的库加入到可运行文件的根目录下,并在文件中指定它们的相对路径即可,希望大家调用顺利吖;
调用python文件主要分为五步:
1.1 在.pro文件中添加python目录;
在.pro文件下添加以下代码,使编辑器能正常识别到python编译器目录
bash
INCLUDEPATH += $$quote(D:\snake\envs\test\include)
LIBS += $$quote(-LD:\snake\envs\test\libs) -lpython39
我使用的是aconda下的虚拟环境,你也可以指定你的python安装目录。其中"python39"为我的python编译器版本,可以在libs目录下查看自己的版本,不要忘记修改哦!!!
1.2 将python集成到QT中
在QT Creator中的工具->选项->环境->外部工具->添加->添加目录(随意添加自己想要的名称即可)->添加工具。点击新创建的工具,配置执行档设置为python.exe的路径即可。
参数: %{CurrentDocument:FilePath}
工作目录: %{CurrentDocument:Path}
1.3 将环境加入环境变量
这个大家应该都不陌生,直接放图
1.4 写入编程代码
在自己的界面代码头文件中加入#include <Python.h>,需要放在#include "mainwindow.h"前;
下面代码为QT页面中调用python函数的例子:
scss
Py_SetPythonHome(L"D:\snake\envs\test"); //设置为自己python环境的根目录
if(!Py_IsInitialized())
{
return; //当没有获取到python根目录时退出
}
PyObject* pModule = PyImport_ImportModule("Py_Module");
if (!pModule){
qDebug()<<"";} //当没有获取到python文件时退出
PyObject* pFunc = PyObject_GetAttrString(pModule, "process_image"); //获取python文件函数指针
PyObject* pValue = PyObject_CallObject(pFunc, NULL);
Py_Finalize();
1.5 为项目加入py库
将python的动态链接库python3.dll, python38.dll及可执行python文件复制到项目运行文件的同目录下,即debug或release的目录下即可(根据自己构建方式进行文件存放)
使用pyinstaller对python文件的环境进行打包,可直接使用pip进行pyinstaller的下载。
arduino
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple/
下一步是pyinstaller使用,conda环境中使用命令
pyinstaller your_python.py_url
最后一步将打包后的dist下的base_library.zip移到项目运行文件的同目录下,我的这个dist目录保存在C:\Users\Administrator\,并把Py_SetPythonHome(L"base_library"); 修改为这个压缩包的路径即可。
2.调用python打包后的exe进行参数传递(这个比较简单,但使用QT调用exe比较慢,且加载的exe文件较大)
2.1 使用pyinstaller对python文件及其环境进行打包,在你下载好pyinstaller的python环境中运行命令即可
css
pyinstaller your_python.py_url -F -p your_python_envs_sitepackge
2.2 调用你的py.exe文件
为方便寻找,将你的.exe文件存放到项目的可执行文件同级目录下,接下来便是使用代码对调用python.exe文件进行参数传递。
首先是加载进程:
ini
QProcess process;
// 要执行的可执行程序路径
QString executablePath = "C:/Users/Administrator/Desktop/untitled/debug/test.exe";
存储需要传递的参数:
ini
QString folderPath = "C:/Users/Administrator/Pictures/OIP.jpg";
// 设置命令行参数
qDebug() << folderPath;s
// 启动可执行程序,并传递命令行参数
QStringList arguments;
arguments << folderPath;
QString line;
启动进程:
scss
process.start(executablePath);
process.write(folderPath.toUtf8());
process.closeWriteChannel(); // 关闭写入通道
process.waitForStarted();
process.waitForReadyRead(); // 等待子进程有输出
if (!process.waitForFinished()) {
qDebug() << "Failed to wait for process to finish!";
}
读取输出:
scss
while (process.canReadLine()) {
line = QString::fromLocal8Bit(process.readLine());
qDebug() << "Output line:" << line;
}
我设置的读取方式是按行读取#process.readLine(),你也可以直接设置读取所有输出#readAllStandardOutput()。
最后一步,如果大家没有在其它机器上运行成功,大概率是因为缺少了qt的动态库,添加进去即可。
这是我在试验了多个环境下以及多个博主方法总结下来的,对于opencv,pillow库都能打包成功,但是对于torch库的打包一直失败,用方法一时报错'获取模块指针失败',感觉大概率是某个库没有打包进去;方法二则是没有读取到输出,尝试过了直接运行.exe,能正常运行。如果有大佬能解答疑惑或给出方向,不胜感激!!
参考文章:Qt C++中调用python,并将软件打包发布,python含第三方依赖_qt 调用python代码如何打包python环境-CSDN博客