Qt下异步使用C++调用Python文件

简介: Qt下异步使用C++调用Python文件

Qt项目中使用到了C++异步调用Python,这里记录一下。

环境

C++ 14,Python 2.7 ,Qt5.4.2用CMake构建,Win10 64位

CMakeLists.txt:Python部分

# Python环境配置
find_package(Python2.7 COMPONENTS Interpreter Development REQUIRED)
include_directories(${PYTHON_INCLUDE_DIR})
C++ 体系复杂,且构建依赖环境,一定要注意各个环节版本是否一致。特别是系统64/32位,两种环境不能互通。

代码

C++头文件

class MyWindow : public QMainWindow
{
Q_OBJECT
public:
    explicit MyWindow(QWidget *parent = 0);
    //销毁资源
    virtual ~MyWindow();
    //异步调用方法需设置为static
    static QString callPython(QString selectedValue);
public slots:
    void onValueChanged();
    void onComboChanged(int idx);
private:
    //任务监听
    QFutureWatcher<QString> *myWatcher;
    QComboBox *myCombo;
    QString myValue;
}
  • QFutureWatcher\<QString\>:为任务监听,QString为异步任务返回值,全局初始化是为了方便获取执行结果及销毁资源,不全局申明可在onValueChanged方法中用下面的代码获取任务监听
QFutureWatcher\<QString\> *myWatcher = dynamic_cast<QFutureWatcher\<QString\> *\>(this->sender());

C++ CXX文件:

#include <Python.h>

MyWindow::MyWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MyWindow),
        m_Model(NULL) {
    ui->setupUi(this);
    myCombo = new QComboBox(this);
    //...初始化combobox
    //绑定comboBoxchange事件
    connect(myCombo, SIGNAL(currentIndexChanged(int)), SLOT(onComboChanged(int)));
    myWatcher = new QFutureWatcher<QString>(this);
    //监听任务结束事件
    connect(myWatcher, SIGNAL(finished()), this, SLOT(onValueChanged())); 
...
  }    
  
  MyWindow::~MyWindow() {
        //销毁资源
        myWatcher->cancel();
        myWatcher->waitForFinished();
        delete myWatcher;
    }
  
void MyWindow::onComboChanged(int idx) {
        QString selectedValue = myCombo->currentData().value<QString>();
        QFuture<QString> myFuture = QtConcurrent::run(MyWindow::callPython, selectedValue);
        cacWatcher->setFuture(myFuture);
    }

QString MyWindow::callPython(QString selectedValue){
            QString result = "";
            if(Py_IsInitialized() == 0){
                Py_Initialize();
            }
            QString filename = "py文件路径";
            QFileInfo filepath = QFileInfo(filename);
            QString path = filepath.absolutePath();
            PyObject *sys = PyImport_ImportModule("sys");
            PyObject *syspath = PyObject_GetAttrString(sys, "path");
            PyList_Insert(syspath, 0, PyString_FromFormat(path.toStdString().c_str()));
            filename = filepath.fileName().split(".")[0];
            PyObject *pName = PyString_FromString(filename.toStdString().c_str());
            PyObject *pModule = PyImport_Import(pName);
            if (pModule != NULL) {
                PyObject *pDict = PyModule_GetDict(pModule);
                PyObject *pFunc = PyDict_GetItem(pDict, PyString_FromString("函数名称"));
                if (pFunc != NULL) {
                    PyObject *pyParams = PyTuple_New(2);
                    PyTuple_SetItem(pyParams, 0, Py_BuildValue("s", selectedValue.toStdString().c_str()));

                    PyObject *pythonResult = PyObject_CallObject(pFunc, pyParams);
                    result = QString(PyString_AsString(pythonResult).c_str());

                } else {
                    msgBox.setText("can't find function");
                    msgBox.exec();
                }
            } else {
                msgBox.setText("can't find dir");
                msgBox.exec();
            }
        } catch (std::exception &err) {
            msgBox.setText(err.what());
            msgBox.exec();
        }
        return result;
}

    void MyWindow::onValueChanged() {
        this->myValue = myWatcher->result();
        // ...业务代码
    }
  • QFutureWatcher:为任务监听
  • QFuture:为异步任务,这里使用QtConcurrent来创建异步任务,也有其它模式,具体请参见官方文档。
  • Py_Initialize为初始化python环境,但在2.7时重复初始环境会导致系统崩溃,可使用Py_IsInitialized()判断是否已初始化过环境。
  • Py_DECREF:看说明是释放资源,但是调用函数第二次运行时也会崩溃,所以实际代码中没有使用。
  • Py_Finalize():同上述原因实际没有使用。
  • PyObject_CallObject:第二个参数为Python函数参数,可有多个,使用PyTuple包裹。

Python源码:

import os

def call_python(param):
    helloStr = "Hello in Python "+param;
    return helloStr;
代码运行过程中每第二次调用python程序就会崩溃,一度以为是QFutureWatcher的异步监听没有释放资源导致,修改为同步任务调试才发现是由于Py_Initialize二次初始化及Py_DECREF释放资源导致。去掉相关资源释放后反而正常了。还是要以实际效果为准

参考资料

https://zhuanlan.zhihu.com/p/149887203

https://blog.csdn.net/iamqianrenzhan/article/details/86516440

目录
相关文章
|
1月前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
14天前
|
存储 算法 文件存储
探秘文件共享服务之哈希表助力 Python 算法实现
在数字化时代,文件共享服务不可或缺。哈希表(散列表)通过键值对存储数据,利用哈希函数将键映射到特定位置,极大提升文件上传、下载和搜索效率。例如,在大型文件共享平台中,文件名等信息作为键,物理地址作为值存入哈希表,用户检索时快速定位文件,减少遍历时间。此外,哈希表还用于文件一致性校验,确保传输文件未被篡改。以Python代码示例展示基于哈希表的文件索引实现,模拟文件共享服务的文件索引构建与检索功能。哈希表及其分布式变体如一致性哈希算法,保障文件均匀分布和负载均衡,持续优化文件共享服务性能。
|
1月前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
61 12
|
2月前
|
监控 网络安全 开发者
Python中的Paramiko与FTP文件夹及文件检测技巧
通过使用 Paramiko 和 FTP 库,开发者可以方便地检测远程服务器上的文件和文件夹是否存在。Paramiko 提供了通过 SSH 协议进行远程文件管理的能力,而 `ftplib` 则提供了通过 FTP 协议进行文件传输和管理的功能。通过理解和应用这些工具,您可以更加高效地管理和监控远程服务器上的文件系统。
65 20
|
2月前
|
存储 数据采集 数据处理
如何在Python中高效地读写大型文件?
大家好,我是V哥。上一篇介绍了Python文件读写操作,今天聊聊如何高效处理大型文件。主要方法包括:逐行读取、分块读取、内存映射(mmap)、pandas分块处理CSV、numpy处理二进制文件、itertools迭代处理及linecache逐行读取。这些方法能有效节省内存,提升效率。关注威哥爱编程,学习更多Python技巧。
112 8
|
2月前
|
存储 JSON 对象存储
如何使用 Python 进行文件读写操作?
大家好,我是V哥。本文介绍Python中文件读写操作的方法,包括文件读取、写入、追加、二进制模式、JSON、CSV和Pandas模块的使用,以及对象序列化与反序列化。通过这些方法,你可以根据不同的文件类型和需求,灵活选择合适的方式进行操作。希望对正在学习Python的小伙伴们有所帮助。欢迎关注威哥爱编程,全栈路上我们并肩前行。
|
2月前
|
存储 算法 Serverless
剖析文件共享工具背后的Python哈希表算法奥秘
在数字化时代,文件共享工具不可或缺。哈希表算法通过将文件名或哈希值映射到存储位置,实现快速检索与高效管理。Python中的哈希表可用于创建简易文件索引,支持快速插入和查找文件路径。哈希表不仅提升了文件定位速度,还优化了存储管理和多节点数据一致性,确保文件共享工具高效运行,满足多用户并发需求,推动文件共享领域向更高效、便捷的方向发展。
|
3月前
|
开发者
Qt异步实现事件的定时执行 - QTimer和QThread的联合使用
通过将QTimer和QThread结合使用,Qt开发者可以实现高效的异步定时任务执行。这种方法不仅可以提升应用程序的响应能力,还可以在复杂的多线程环境中保持代码的简洁和可维护性。希望本文的详细介绍和示例代码能够帮助您更好地理解和应用这一技术。
172 14
|
3月前
|
计算机视觉 Python
如何使用Python将TS文件转换为MP4
本文介绍了如何使用Python和FFmpeg将TS文件转换为MP4文件。首先需要安装Python和FFmpeg,然后通过`subprocess`模块调用FFmpeg命令,实现文件格式的转换。代码示例展示了具体的操作步骤,包括检查文件存在性、构建FFmpeg命令和执行转换过程。
100 7
WK
|
4月前
|
开发框架 开发工具 C++
C++跨平台框架Qt
Qt是一个功能强大的C++跨平台应用程序开发框架,支持Windows、macOS、Linux、Android和iOS等操作系统。它提供了250多个C++类,涵盖GUI设计、数据库操作、网络编程等功能。Qt的核心特点是跨平台性、丰富的类库、信号与槽机制,以及良好的文档和社区支持。Qt Creator是其官方IDE,提供了一整套开发工具,方便创建、编译、调试和运行应用程序。Qt适用于桌面、嵌入式和移动应用开发。
WK
131 5