def _dispatch(self, func, args=None):
        """Send message to parent process

        Arguments:
            func (str): Name of function for parent to call
            args (list, optional): Arguments passed to function when called

        """

        data = json.dumps(
            {
                "header": "pyblish-qml:popen.request",
                "payload": {
                    "name": func,
                    "args": args or list(),
                }
            }
        )

        # This should never happen. Each request is immediately
        # responded to, always. If it isn't the next line will block.
        # If multiple responses were made, then this will fail.
        # Both scenarios are bugs.
        assert self.channels["response"].empty(), (
            "There were pending messages in the response channel")

        sys.stdout.write(data + "\n")
        sys.stdout.flush()

        try:
            message = self.channels["response"].get()

            if six.PY3:
                response = json.loads(message)
            else:
                response = _byteify(json.loads(message, object_hook=_byteify))

        except TypeError as e:
            raise e

        else:
            assert response["header"] == "pyblish-qml:popen.response", response
            return response["payload"]
Send message to parent process

        Arguments:
            func (str): Name of function for parent to call
            args (list, optional): Arguments passed to function when called