即使使用QThread执行,python / pyqt子进程也会阻止GUI

时间:2015-03-21 21:40:47

标签: python subprocess pyqt4 qthread

我有一个名为filea的主脚本用于执行主程序。其他脚本fileb用于执行其他重要功能。我还有其他文件filecfiled ...用于执行特定功能。为便于理解,我仅考虑fileafileb

以下是我尝试执行的filea的工作流程: -

from PyQt4 import QtGui
from PyQt4 import QtCore
from fileb import ClassB

class ClassA(fileb.ClassB, QtGui.QDialog, Ui_Dialog):
    """
    Main Class.
    """
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

        self.ui.button1.clicked.connect(self.some_fun)

        self.progress_thread = GuiInstallProgress()
        self.progress_thread.update.connect(self.ui.progressbar.setValue)
        self.progress_thread_imager.finished.connect(self.process_finished)

    def some_fun(self):
        # do some coding
        # do some conditions
        progress = GuiInstallProgress()
        progress.start()

    def process_finished(self):
        #do some coding
        QtGui.QMessageBox.information(self, 'Finished...', 'Process finished')


class GuiInstallProgress(QtCore.QThread):
    update = QtCore.pyqtSignal(int)
    status = QtCore.pyqtSignal(str)
    finished = QtCore.pyqtSignal()

    def __init__(self):
        QtCore.QThread.__init__(self)
        self.install = ClassB()
        self.thread = GenericThread(self.install.dd_function)

    def __del__(self):
        self.wait()

    def run(self):
        self.thread.start()
        while self.thread.isRunning():
            self.update.emit(some_number_from_dd_function)  # <-- Problem. Nothing is emitted.
            print some_number_from_dd_function  # <-- this prints number to terminal.
            if not self.thread.isFinished() and some_number_from_dd_function == 100:
                self.status.emit("Please wait...")
        self.update.emit(100)  # <-- Problem. Nothing is emitted.
        self.update.emit(0)  # <-- Problem. Nothing is emitted.
        self.status.emit("")

        if self.thread.isFinished():
            self.finished.emit()  # <-- Problem. Nothing is emitted.
            print "Process finished..."
        return

class GenericThread(QtCore.QThread):

    def __init__(self, function, *args, **kwargs):
        QtCore.QThread.__init__(self)
        self.function = function
        self.args = args
        self.kwargs = kwargs

    def __del__(self):
        self.wait()

    def run(self):
        self.function(*self.args, **self.kwargs)
        return

app = QtGui.QApplication(sys.argv)
window = AppGui()
ui = Ui_Dialog()
window.show()
sys.exit(app.exec_())

以下是fileb的代码概念: -

import subprocess
# other imports

class ClassB(QtGui.QDialog, Ui_Dialog):

    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

    def dd_function(self):

        command = ['dd', 'if=~/input.img', 'of=~/output.img', 'bs=1M']
        dd_process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
        while dd_process.poll() is None:
            time.sleep(.1)
            dd_process.send_signal(signal.SIGUSR1)
            dd_process.stderr.flush()
            while True:
                out_error = dd_process.stderr.readline()
                if out_error:
                    if 'bytes' in out_error:
                        copied = int(out_error.split(' ', 1)[0])
                        some_number_from_dd_function = round((float(copied) / float(in_file_size) * 100))
                        break
        if dd_process.poll() is not None:
            os.system("sync")

基本上fileb用于dd功能并从filea执行。专用GuiInstallProgress仅用于根据dd程序的进度发出信号。但是,在执行dd操作时,进度条没有变化(在终端上打印相同的值)。 GUI完全挂起。确保没有信号从GuiInstallProgress发出,因为在dd进程结束后程序没有弹出消息框。在dd过程完成后,GUI恢复正常。

我已经在filec中使用的类似方法(但不是dd程序,而是一些大文件复制操作)。它解决了一个问题。

我在哪里弄错了? B类通过互联网上的大量文档消失但我无法解决这个问题。

感谢任何帮助。

0 个答案:

没有答案