开发工具:Qt5.9.9_x64 python3.6.13_x64 vs2015
系统环境:win10,win11都行
vs2015 、python和qt的安装我就不说了,网上很多教程,我这里开发环境是64位,需要注意的就是安装qt的时候一定要选MSCV2015_x64这个选项,其他的随你的需求。
安装好后,首先确定qt能跑你的项目 ,然后我们在测试python环境,在外部工具中设置中画红线的地方填入python安装目录,
参数 :%{CurrentDocument:FilePath};
工作目录:%{CurrentDocument:Path},左边的工具名都是添加自己建的。
这些弄好后,在资源文化中加入测试的python文件,然后点开文件,点到如图所示中的python3.6,
如果能运行就说明python环境没什么问题,就可以接下来的步骤 。
接下来在项目中添加 外部库,按如下的图片做完,一直点下一步 就行。
然后主要调用代码就是这些,我只用了这些。
PyThreadStateLock.h
//将全局解释器锁和线程的相关操作用类封装
#ifndef PYTHREADSTATELOCK_H
#define PYTHREADSTATELOCK_H
#include<Python.h>
class PyThreadStateLock
{
public:
PyThreadStateLock(void)
{
_save = nullptr;
nStatus = 0;
nStatus = PyGILState_Check(); //检测当前线程是否拥有GIL
PyGILState_STATE gstate;
if (!nStatus)
{
gstate = PyGILState_Ensure(); //如果没有GIL,则申请获取GIL
nStatus = 1;
}
_save = PyEval_SaveThread();
PyEval_RestoreThread(_save);
}
~PyThreadStateLock(void)
{
_save = PyEval_SaveThread();
PyEval_RestoreThread(_save);
if (nStatus)
{
PyGILState_Release(gstate); //释放当前线程的GIL
}
}
private:
PyGILState_STATE gstate;
PyThreadState *_save;
int nStatus;
};
#endif // PYTHREADSTATELOCK_H
Qtpython::Qtpython()
{//初始化
if (!Py_IsInitialized())
{
//1.初始化Python解释器,这是调用操作的第一步
Py_Initialize();
if (!Py_IsInitialized()) {
qDebug("Initial Python failed!");
// emit failed();
}
else {
//执行单句Python语句,用于给出调用模块的路径,否则将无法找到相应的调用模块
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./Qtpython/')");//python文件在的相对路径
// 初始化线程支持
PyEval_InitThreads();
// 启动子线程前执行,为了释放PyEval_InitThreads获得的全局锁,否则子线程可能无法获取到全局锁。
PyEval_ReleaseThread(PyThreadState_Get());
qDebug("Initial Python Success!");
}
}
}
void Qtpython::on_openButton_clicked()
{
class PyThreadStateLock PyThreadLock;//加上线程锁
PyObject* pModule = PyImport_ImportModule("scriptSecond");
if (!pModule)
{
qDebug()<<"Cant open python file!\n";
return ;
}
PyObject* pFunhello= PyObject_GetAttrString(pModule,"hhh");
if(!pFunhello){
qDebug()<<"Get function hello failed";
return;
}
//调用temperImg函数
PyObject_CallFunction(pFunhello,nullptr);
PyErr_Print();//报错信息
//结束,释放python
// Py_Finalize();
}
这里不是很建议用Py_Finalize()清除内存 ,英文文档中提到这个函数是没办法完全清除的,所以用了之后很可能调用两到三次就会报错的,这里我就不用了。到这里基本就能用了,可能还会出现以下问题:
1.在 “;”前出错 类似问题,解决办法是在object.h,*slots改为 * _slots就行了。
2.没有python36_d,在pyconfig.h中把 ”python36_d“ 改为 ”python36“就行了。
3.最无语的报错 ”程序异常结束“,如果你也出现 了以下的错误,恭喜你和我一样幸运 ,巨坑。
在自己的python安装目录下找到这个鬼,然后 复制 到libs中就可以。这坑在没有任何错误信息。
以上就是qt5调用python,以及报错的全部内容,如果你有其他问题欢迎评论留言,另外想要 资源包的可以用 下面网址下载: