QProcess PyQt5 TypeError - PullRequest
       94

QProcess PyQt5 TypeError

1 голос
/ 04 марта 2020

У меня есть приложение, которое использует много QProcess, и иногда два процесса запускаются одновременно. Вот почему у меня много функций для readyReadStandardOutput.connect (). поэтому моя идея состоит в том, чтобы создать два или три класса для похожих ситуаций и значительно сократить код. Я смог проверить, что в этом вопросе есть решение, которое мне нравится

{ ссылка }

, и есть другое:

{ ссылка }

Я пытался создать класс, который может помочь мне из класса первой ссылки, однако я не добился успеха, потому что он генерирует ошибку

QObject::connect: Cannot connect ProcessOutputReader::produce_output(QString) to (null)::append_output(QString)
Traceback (most recent call last):
  File "process2.py", line 22, in funRun
    self.process.run_process()
  File "process2.py", line 40, in run_process
    self.process.produce_output.connect(self.append_output)
TypeError: connect() failed between ProcessOutputReader.produce_output[str] and append_output()

это мой код:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class windowProcess(QMainWindow):
    def __init__(self):
        super(windowProcess, self).__init__()
        self.setWindowTitle("Windows Process")
        self.resize(475, 253)
        self.btn_run = QPushButton("run",self)
        self.btn_run.setGeometry(388, 20, 75, 25)
        self.text_edit = QTextEdit(self)

        self.text_edit.setGeometry(20, 50, 441, 191)

        self.btn_run.clicked.connect(self.funRun)

    def funRun(self):
        self.process = myClassProcess()
        self.process.run_process()


    @pyqtSlot(str)
    def append_output(self, text):
        self.text_edit.append(text)

    @pyqtSlot(str)
    def append_error(self, text):
        self.text_edit.append(text)


class myClassProcess(object):
    def __init__(self, parent=None):
        self.info = []

    def run_process(self):        
        self.process = ProcessOutputReader()
        cmd = "ping www.google.com"
        self.process.produce_output.connect(self.append_output)
        self.process.produce_error.connect(self.append_error)
        self.process.start(cmd)

    @pyqtSlot(str)
    def append_output(self, text):
        print(text)
        self.info.append(text)
        #return text            

    @pyqtSlot(str)
    def append_error(self, text):
        self.info.append(text)
        #return text            

    def getInfo(self):
        print(self.info)


class ProcessOutputReader(QProcess):
    produce_output = pyqtSignal(str)
    produce_error = pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent=parent)

        codec = QTextCodec.codecForLocale()
        self._decoder_stdout = codec.makeDecoder()
        # only necessary when stderr channel isn't merged into stdout:
        self._decoder_stderr = codec.makeDecoder()

        self.readyReadStandardOutput.connect(self._ready_read_standard_output)
        # only necessary when stderr channel isn't merged into stdout:
        self.readyReadStandardError.connect(self._ready_read_standard_error)

    @pyqtSlot()
    def _ready_read_standard_output(self):
        raw_bytes = self.readAllStandardOutput()
        text = self._decoder_stdout.toUnicode(raw_bytes)
        self.produce_output.emit(text)

    # only necessary when stderr channel isn't merged into stdout:
    @pyqtSlot()
    def _ready_read_standard_error(self):
        raw_bytes = self.readAllStandardError()
        text = self._decoder_stderr.toUnicode(raw_bytes)
        self.produce_error.emit(text)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ventana = windowProcess()
    ventana.show()
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 04 марта 2020

Декоратор pyqtSlot имеет значение только для QObject, в моем случае myClassProcess не вызывает проблему, на которую вы указываете.

Учитывая это, есть 2 решения:

  • Не используйте @pyqtSlot в append_output и append_error методах myClassProcess.

  • Или делайте myClassProcess объектом QObject:

    class myClassProcess(<b>QObject</b>):
        def __init__(self, parent=None):
            <b>super().__init__(parent)</b>
            self.info = []
...