code: def listen(self):
          
  
          def _listen():
              """This runs in a thread"""
              HEADER = "pyblish-qml:popen.request"
  
              for line in iter(self.popen.stdout.readline, b""):
  
                  if six.PY3:
                      line = line.decode("utf8")
  
                  try:
                      response = json.loads(line)
  
                  except Exception:
                      # This must be a regular message.
                      sys.stdout.write(line)
  
                  else:
                      if (hasattr(response, "get") and
                              response.get("header") == HEADER):
  
                          payload = response["payload"]
                          args = payload["args"]
  
                          func_name = payload["name"]
  
                          wrapper = _state.get("dispatchWrapper",
                                               default_wrapper)
  
                          func = getattr(self.service, func_name)
                          result = wrapper(func, *args)  # block..
  
                          # Note(marcus): This is where we wait for the host to
                          # finish. Technically, we could kill the GUI at this
                          # point which would make the following commands throw
                          # an exception. However, no host is capable of kill
                          # the GUI whilst running a command. The host is locked
                          # until finished, which means we are guaranteed to
                          # always respond.
  
                          data = json.dumps({
                              "header": "pyblish-qml:popen.response",
                              "payload": result
                          })
  
                          if six.PY3:
                              data = data.encode("ascii")
  
                          self.popen.stdin.write(data + b"\n")
                          self.popen.stdin.flush()
  
                      else:
                          # In the off chance that a message
                          # was successfully decoded as JSON,
                          # but *wasn't* a request, just print it.
                          sys.stdout.write(line)
  
          if not self.listening:
              self._start_pulse()
  
              if self.modal:
                  _listen()
              else:
                  thread = threading.Thread(target=_listen)
                  thread.daemon = True
                  thread.start()
  
              self.listening = True
docs: Listen to both stdout and stderr
  
          We'll want messages of a particular origin and format to
          cause QML to perform some action. Other messages are simply
          forwarded, as they are expected to be plain print or error messages.