Qt 調用Python腳本方法及遇到的問題


1、背景

  簡單說一下需求,Qt開發的上位機界面程序,需要調用Python編寫的算法跑一個結果返回到界面上顯示。

2、度娘出一篇博客,按照步驟進行環境搭建和簡單的代碼測試

  環境搭建請參照如下博客地址:

    博客:① https://blog.csdn.net/cholenmine/article/details/82854301

       ② https://blog.csdn.net/yinyuchen1/article/details/77775851

  主要代碼如下:

#include "Python.h"

void MainWindow::test()

{
    //進行初始化
    Py_Initialize();
    //如果初始化失敗,返回
    if(!Py_IsInitialized())
    {
        qDebug()<<"11111111111111111111";
        return ;
    }

    //加載模塊,模塊名稱為myModule,就是myModule.py文件
    PyObject *pModule = PyImport_ImportModule("myModule");
    //如果加載失敗,則返回
    if(!pModule)
    {
        qDebug()<<"2222222222222222";
        return;
    }

   //加載函數greatFunc
    PyObject * pFuncHello = PyObject_GetAttrString(pModule, "greatFunc");

    //如果失敗則返回
    if(!pFuncHello)
    {
        qDebug()<<"3333333333333333333333";
        return ;
    }        
}

3、根據目前的具體需求,我需要在開啟一個線程來調用Python腳本,於是新建了一個線程類,調用方法還是用的上面的示例代碼。

  .h文件

#ifndef CALCSCORETHREAD_H
#define CALCSCORETHREAD_H

#include <QObject>
#include <QThread>
#include <Python.h>

class CalcScoreThread : public QThread
{
    Q_OBJECT
public:
    CalcScoreThread(QObject *parent = nullptr);

    // html轉化為PDF
    QString saveHtmlToPDF(QString str);

protected:
    void run();

private:
    QString m_ScoreType;
    QString m_LabelPath;
};

#endif // CALCSCORETHREAD_H

  cpp文件

#include "CalcScoreThread.h"
#include "LoggerInfo.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QDir>

CalcScoreThread::CalcScoreThread(QObject *parent) : QThread(parent)
{

}

void CalcScoreThread::SetScoreType(const QString &type)
{
    m_ScoreType = type;
}

void CalcScoreThread::run()
{
    Py_Initialize();

    //測試集路徑
    QString setsPath =  QCoreApplication::applicationDirPath()+"/datasets/Divide_Labels";
    QString name ="main_SCORE";
    LoggerInfo::GetInstance()->WriteLog("Start Import Module!");

    PyObject* pModule  = PyImport_ImportModule("main_SCORE");
    if (!pModule)
    {
       qDebug() << "Cant open python file!";
       return;
    }

    LoggerInfo::GetInstance()->WriteLog("Import Module Succ!");
    //獲取模塊中的函數
    PyObject* pFunc = PyObject_GetAttrString(pModule,"main");

    if(!pFunc)
    {
        qDebug() << "Get function failed!";
        return;
    }

    QString strEnv = "5,2,2,3";
    PyObject* pArgs = PyTuple_New(4);
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",m_ScoreType.toStdString().c_str()));
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("s",m_LabelPath.toStdString().c_str()));
    PyTuple_SetItem(pArgs, 2, Py_BuildValue("s",setsPath.toStdString().c_str()));
    PyTuple_SetItem(pArgs, 3, Py_BuildValue("s",strEnv.toStdString().c_str()));

    PyObject* pReturn = PyObject_CallObject(pFunc, pArgs);

    if(pReturn)
    {
        qDebug() << "succ  ------";
    }

    Py_Finalize();

    if(!strResult.isEmpty())
    {
        emit SignalScoreResult(strResult);
    }

}

  現在問題來了:

  ① 第一次調用python腳本,能夠正常調用並且得到結果。

  ② 不關閉主界面,接着進行第二次調用,軟件直接崩潰,崩潰的行數是PyImport_ImportModule()函數,如下圖所示:

  

 

 

  最開始分析的原因:① 出現了空指針 

           ② 第二次調用時,第一次的資源沒有釋放,占用python腳本,導致PyImport_ImportModule()函數不能將模塊導入

4、最后差資料發現,因為我這里使用的是線程,C++多線調用python時必須要控制GIL

  參照如下博客的方法才得以解決這個問題,對於小白初次線程中調用Python,鬼知道要控制什么GIL,雖然問題解決了,到現在都沒去看GIL是個什么鬼  

  https://blog.csdn.net/qq_42938320/article/details/101770269

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM