title: Run command with PyQt5 and getting the stdout and stderr
body: <p>I want to run command with PyQt5. And I want to get the stdout and stderr in time order and in real-time.</p>
  
  <p>I separated into UI class and Worker class. There are several UI classes, but for simplicity, I've specified just one.</p>
  
  <p>I've tried to solve this problem, but I can't. I can't connect between the Worker thread and logger function. </p>
  
  <p><strong>test_ui.py</strong></p>
  
  <pre class="lang-py prettyprint-override"><code>import sys
  import subprocess
  from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
  from PyQt5.QtWidgets import QPushButton, QTextEdit
  from worker import Worker
  
  
  class TestUI(QWidget):
      def __init__(self):
          super().__init__()
          self.worker = Worker()
          self.btn1 = QPushButton("Button1")
          self.btn2 = QPushButton("Button2")
          self.btn3 = QPushButton("Button3")
          self.result = QTextEdit()
          self.init_ui()
  
      def init_ui(self):
          self.btn1.clicked.connect(self.press_btn1)
          self.btn2.clicked.connect(self.press_btn2)
          self.btn3.clicked.connect(self.press_btn3)
  
          hlayout1 = QHBoxLayout()
          hlayout1.addWidget(self.btn1)
          hlayout1.addWidget(self.btn2)
          hlayout1.addWidget(self.btn3)
  
          hlayout2 = QHBoxLayout()
          hlayout2.addWidget(self.result)
  
          vlayout = QVBoxLayout()
          vlayout.addLayout(hlayout1)
          vlayout.addLayout(hlayout2)
  
          self.setLayout(vlayout)
          self.show()
  
      def press_btn1(self):
          command1 = "dir"
          path = "./"
          self.worker.run_command(command1, path)
          self.worker.outSignal.connect(self.logging)
  
      def press_btn2(self):
          command2 = "cd"
          path = "./"
          self.worker.run_command(command2, path)
          self.worker.outSignal.connect(self.logging)
  
      def press_btn3(self):
          command3 = "whoami"
          path = "./"
          self.worker.run_command(command3, path)
          self.worker.outSignal.connect(self.logging)
  
      def logging(self, str):
          self.result.append(str.strip())
  
  
  if __name__ == "__main__":
      APP = QApplication(sys.argv)
      ex = TestUI()
      sys.exit(APP.exec_())
  </code></pre>
  
  <p><strong>worker.py</strong></p>
  
  <pre class="lang-py prettyprint-override"><code>
  from PyQt5.QtCore import QProcess, pyqtSignal
  
  
  class Worker:
      outSignal = pyqtSignal(str)
      errSignal = pyqtSignal(str)
  
      def __init__(self):
          self.proc = QProcess()
  
      def run_command(self, cmd, path):
          self.proc.setWorkingDirectory(path)
          self.proc.setProcessChannelMode(QProcess.MergedChannels)
          self.proc.readyReadStandardOutput.connect(self.onReadyStandardOutput)
          self.proc.finished.connect(self.proc.deleteLater)
          self.proc.start(cmd)
  
      def onReadyStandardOutput(self):
          result = self.proc.readAllStandardOutput().data().decode()
          self.outSignal.emit(result)
  
      def onReadyStandardError(self):
          result = self.proc.readAllStandardError().data().decode()
          self.errSignal.emit(result)
  </code></pre>
  
  <p>Update:</p>
  
  <p>Applying <a href="https://stackoverflow.com/a/60174168/6622587">here solution</a> and making the following modifications still fails the code:</p>
  
  <pre class="lang-py prettyprint-override"><code>@pyqtSlot()
  def press_btn1(self):
      command1 = "dir"
      path = "./"
      self.worker.run_command(command1, path)
  
  @pyqtSlot()
  def press_btn2(self):
      command2 = "cd"
      path = "./"
      self.worker.run_command(command2, path)
  
  @pyqtSlot()
  def press_btn3(self):
      command3 = "test.bat"
      path = "./"
      self.worker.run_command(command3, path)
  
  @pyqtSlot(str)
  def logging(self, msg):
      msg = msg.strip()
      if msg != "":
          self.result.append(msg)
  </code></pre>
  
  <p><strong>test.bat</strong></p>
  
  <pre><code>@echo off
  
  echo "Output 1"
  timeout /t 1
  1&gt;&amp;2 echo "Error 1"
  timeout /t 1
  echo "Output 2"
  timeout /t 1
  1&gt;&amp;2 echo "Error 2"
  </code></pre>
  
  <hr>
  
  <h2>Batchfile Issue</h2>
  
  <p>This is the result when I run it through the command prompt.</p>
  
  <p>It outputs one line every second in real-time.</p>
  
  <pre><code>"Output 1"
  
  Waiting for 0 seconds, press a key to continue ...
  "Error 1"
  
  Waiting for 0 seconds, press a key to continue ...
  "Output 2"
  
  Waiting for 0 seconds, press a key to continue ...
  "Error 2"
  </code></pre>
  
  <p>This is the result of the application.</p>
  
  <p>It outputs whole lines after 3 seconds. And the time order is not right.</p>
  
  <pre><code>"Output 1"
  
  Waiting for 1 seconds, press a key to continue ...0
  
  Waiting for 1 seconds, press a key to continue ...0
  "Output 2"
  
  Waiting for 1 seconds, press a key to continue ...0
  "Error 1"
  "Error 2"
  </code></pre>