weiweiqiao的个人主页

http://www.qtcn.org/bbs/u/88727  [收藏] [复制]

weiweiqiao

撑住,别输!

  • 28

    关注

  • 38

    粉丝

  • 20

    访客

  • 等级:侠客
  • 总积分:156
  • 保密,1980-12-14

最后登录:2024-04-14

更多资料

日志

Pyside2中子进程的启动与关闭

2021-06-03 19:11

Pyside2是Qt框架的Python实现,借着Python的大热,对推广Qt框架也是很好的推动,Qt对线程有专门的类QThread,但是在C++下的子线程处理用在Pyside2中虽然能正常退出程序,但是返回的code始终不是0。所以采用信号告知运行结束的方式进行处理。

C++线程处理:


Ui_process为用户操作处理类,将用户操作转给不同的类处理。在这里有File_process、Track_process及各自对应的子线程。
  1. #ifndef UI_PROCESS_H
    #define UI_PROCESS_H


    #include <QObject>
    #include <QThread>


    class File_process;
    class Track_process;
    class Track_data;


    class Ui_process : public QObject
    {
        Q_OBJECT
    public:
        explicit Ui_process(QObject *parent = nullptr);
        ~Ui_process();


        void get_filter_conditions(QMap<QString, QVariant>* filter, QList<Track_data* >* list);


    public slots:
        void sl_open_files();
        void sl_split_data_to_files();
        void sl_exit_application();


    signals:
        void si_open_files(QStringList files_name);


        void si_split_data_to_files(QStringList files_name);


        void si_send_track_to_model(Track_data* data);


        void si_clear_model_();


        void si_send_filter_and_track_to_process(QMap<QString, QVariant>* filter,
                                                 QList<Track_data* >* list);


        void si_updte_model_by_filter(int row, bool flag);


    private:
        void init_connects();


        /***************************************************************************
         @Date     2021-05-23
         @Author   qiaowei
         @Contact  weiweiqiao@126.com
         @Version  1.0
         @Brief    Create a sub thread
         @Param    thread sub thread
         @Param    process pointer moved into sub thread
        ***************************************************************************/
        void start_sub_thread(QThread& thread, QObject* process);


    private:
        // 文件处理类及对应子线程
        File_process* file_process_;
        QThread file_thread_;


        // 航迹处理类及对应子线程
        Track_process* track_process_;
        QThread track_thread_;


    };


    #endif // UI_PROCESS_H
Ui_process类实现:
  1. #include <QApplication>
    #include <QFileDialog>
    #include <QtDebug>
    #include <QMetaType>
    #include "ui_process.h"
    #include "file_process.h"
    #include "track_process.h"
    #include "../data_modules/track_data.h"

    Ui_process::Ui_process(QObject *parent)
        : QObject(parent)
        , file_process_(new File_process())
        , track_process_(new Track_process())
    {
        init_connects();
    }

    Ui_process::~Ui_process()
    {
        if ((nullptr != track_process_)
                && (thread() == track_process_->thread())) {
            delete track_process_;
            track_process_ = nullptr;
        }

        track_thread_.quit();
        track_thread_.wait();

        if ((nullptr != file_process_)
                && (thread() == file_process_->thread())) {
            delete file_process_;
            file_process_ = nullptr;
        }

        file_thread_.quit();
        file_thread_.wait();
    }

    void Ui_process::get_filter_conditions(QMap<QString, QVariant> *filter, QList<Track_data *> *list)
    {
        start_sub_thread(track_thread_, track_process_);

        emit si_send_filter_and_track_to_process(filter, list);
    }

    void Ui_process::sl_open_files()
    {
        QStringList files_list = QFileDialog::getOpenFileNames();

        if ( !files_list.isEmpty()) {
            emit si_clear_model_();

            start_sub_thread(file_thread_, file_process_);

            emit si_open_files(files_list);
        }
    }

    void Ui_process::sl_split_data_to_files()
    {
        QStringList files_list = QFileDialog::getOpenFileNames();

        if ( !files_list.isEmpty()) {
            start_sub_thread(file_thread_, file_process_);

            emit si_split_data_to_files(files_list);
        }
    }

    void Ui_process::sl_exit_application()
    {
        QApplication::closeAllWindows();
    }

    void Ui_process::init_connects()
    {
        connect(this, &Ui_process::si_split_data_to_files,
                file_process_, &File_process::sl_split_data_to_files);

        connect(this, &Ui_process::si_send_filter_and_track_to_process,
                track_process_, &Track_process::sl_filter_track_data);

        connect(this, &Ui_process::si_open_files,
                file_process_, &File_process::sl_open_files_to_show);

        connect(file_process_, &File_process::si_send_track_to_model,
                this, &Ui_process::si_send_track_to_model);

        connect(track_process_, &Track_process::si_update_track_by_filter,
                this, &Ui_process::si_updte_model_by_filter);
    }

    void Ui_process::start_sub_thread(QThread &thread, QObject *process)
    {
        if ( !thread.isRunning()) {
            if (nullptr != process) {
                process->moveToThread(&thread);

                connect(&thread, &QThread::finished, process, &QObject::deleteLater);

                thread.start();
            }
        }
    }


在析构函数中对子线程进行的比对,当线程不为空指针且在主线程中,说明子线程未启动,直接delete;反之,子线程已启动,使用quit,wait方法进行关闭处理。

Python处理:


在UiProcess类中定义关闭子线程函数sl_stop_sub_thread(self, code: int),当在子线程运行的函数结束时,发射结束信号,调用sl_stop_sub_thread(self, code: int)
  1. # !/usr/bin/env python
    # encoding: utf-8
    # @File    : ui_process_module.py
    # @Time    : 2021/5/17
    # @Author  : qiaowei
    # @Version : 1.0
    # @Email   : weiweiqiao@126.com
    # @License : (C) Copyright 2013-2021
    # @Brief   :




    import ctypes
    from PySide2.QtCore import QObject
    from PySide2.QtCore import QThread
    from PySide2.QtWidgets import QApplication
    from PySide2.QtWidgets import QFileDialog
    from PySide2.QtCore import Slot
    from PySide2.QtCore import Signal
    from process_package.data_process_module import DataProcess




    class UiProcess(QObject):
        def __init__(self):
            super(UiProcess, self).__init__()
            # 在构造函数中创建变量对象__data_process,__thread,在私有函数__instance中实例化
            self.__data_process = None
            self.__thread = None


            self.__instance()
            self.__connect()




        @Slot()
        def sl_open_track_files(self):
            files = QFileDialog.getOpenFileNames()[0]
            if 0 != len(files):
                pass




        @Slot()
        def sl_split_data_to_files(self):
            """
            打开文件,将文件内容按条件保存到不同的文件中


            :return: None
            """
            files = QFileDialog.getOpenFileNames()[0]
            # 选取文件数量不为0
            if 0 != len(files):
                if self.__setup_sub_thread(self.__thread, self.__data_process):
                    self.si_split_data_to_files.emit(files)




        @Slot()
        def sl_quit_application(self):
            """
            Slot function, quit application


            :return: None
            """
            QApplication.closeAllWindows()




        @Slot(int)
        def sl_stop_sub_thread(self, code: int):
            """
            根据标志位关闭子线程


            :param code: 子线程标志位。0为__thread


            :return: None
            """
            if 0 == code:
                self.__thread.exit()




        def __instance(self):
            self.__data_process = DataProcess()
            self.__thread = QThread()




        def __connect(self):
            # 打开文件列表,将文件的数据根据条件保存到不同文件中
            self.si_split_data_to_files.connect(self.__data_process.sl_split_data_to_files)
            # 子线程的任务结束后调用线程关闭函数
            self.__data_process.si_stop_sub_thread.connect(self.sl_stop_sub_thread)




        def __setup_sub_thread(self, thread: QThread, process: QObject):
            """
            启动子线程


            :param thread: 要启动的子线程
            :param process: 迁移到子线程中的变量


            :return: True 子线程正常启动;False 子线程启动失败
            """
            if not thread.isRunning():
                process.moveToThread(thread)
                thread.start()


                return True


            return False


        # Signal
        # 打开文件,读取数据,显示到Model/View
        si_open_files = Signal(list)


        # 打开文件,读取数据,将数据根据条件保存到不同文件中
        si_split_data_to_files = Signal(list)
迁入子线程的类,sl_split_data_to_files(self, file_list: list)函数在运行结束前发射结束信号
  1. # !/usr/bin/env python
    # encoding: utf-8
    # @File    : data_process_module.py
    # @Time    : 2021/5/17
    # @Author  : qiaowei
    # @Version : 1.0
    # @Email   : weiweiqiao@126.com
    # @License : (C) Copyright 2013-2021
    # @Brief   : 处理数据类
    # @History : 20210521 添加sl_split_data_to_files函数


    from PySide2.QtCore import QObject
    from PySide2.QtCore import QDateTime
    from PySide2.QtCore import QFile
    from PySide2.QtCore import QIODevice
    from PySide2.QtCore import QTextStream
    from PySide2.QtCore import Slot
    from PySide2.QtCore import Signal
    from data_module.constant_module import SYS_RECV_PROCESS


    class DataProcess(QObject):
        def __init__(self):
            super(DataProcess, self).__init__()


        def sl_open_files_to_show_track(self, file_list: list):
            if 0 == len(file_list):
                return
            


        @Slot(list)
        def sl_split_data_to_files(self, file_list: list):
            """
            根据传入的文件名列表。依次读取每个文件中数据并按设置保存到新建的文件中

            :param file_list: 打开的文件名列表

            :return: None
            """
            if 0 == len(file_list):
                return

            time = QDateTime().currentDateTime().toString()

            # 创建保存process数据的文档
            save_process_file = QFile(file_list[0].replace('.log', '_PROCESS_.log'))
            # save_process_file = QFile('process.log')

            try:
                for name in file_list:
                    file = QFile(name)
                    if not file.exists():
                        return
                    if not file.open(QIODevice.ReadOnly | QIODevice.Text):
                        return

                    in_stream = QTextStream(file)
                    # in_stream.setCodec('utf-8')
                    in_stream.setAutoDetectUnicode(True)

                    # 续写文件模式打开新创建的文件
                    if save_process_file.open(QFile.WriteOnly | QFile.Truncate | QFile.Append):
                        out_stream_process = QTextStream(save_process_file)

                    # 按行遍历文件,将符合要求的数据保存到save_process_file文件中
                    while not in_stream.atEnd():
                        content = in_stream.readLine()
                        if SYS_RECV_PROCESS in content:
                            out_stream_process << content.replace('sysRecv 1 process', '') << '\n'

                    file.close()
                    save_process_file.close()
            except IOError as io_error:
                print('File error:' + str(io_error))
            finally:
                if file.isOpen():
                    file.close()
                if save_process_file.isOpen():
                    save_process_file.close()
                # 发射退出子线程的信号
                self.si_stop_sub_thread.emit(0)


        # 信号,线程完成任务后,向调用线程的对象发射信号
        si_stop_sub_thread = Signal(int)



这是目前我能想到的处理方式,如有更好的,希望不吝赐教



分类:默认分类|回复:0|浏览:547|全站可见|转载
 

下一篇:

上一篇:

Powered by phpwind v8.7 Certificate Copyright Time now is:04-27 04:42
©2005-2016 QTCN开发网 版权所有 Gzip disabled