Andy Pender
Andy Pender

Reputation: 106

Non-blocking IPython Qt console in a PyQt application

I'm looking to embed an IPython Qt console in my application using RichJupyterWidget. It seems I have two choices as to how I set up the console:

  1. Use QtInProcessKernelManager (as below). In this case the kernel blocks when executing code which is non-ideal as some commands I expect users to run take up to a minute.
  2. Use QtKernelManager (as in this GitHub example) to create a normal IPython kernel launched as a subprocess. In this case I can't pass the namespace from my main process into the kernel and the kernel can't communicate with the main application. Both of these are requirements.

Is it possible to have the best of both worlds here? I'd like to have a non-blocking console, that contains the same namespace as my main process and can send signals to the main application. A similar question has been asked by waszil in the comments here. Using a QThread with QtInProcessKernelManager is a possibility but I'm not sure what method I should thread.

from qtconsole.qt import QtGui
from qtconsole.rich_jupyter_widget import RichJupyterWidget
from qtconsole.inprocess import QtInProcessKernelManager

class ConsoleWidget(RichJupyterWidget):


    def __init__(self, namespace={}, customBanner=None, *args, **kwargs):
        super(ConsoleWidget, self).__init__(*args, **kwargs)

        if customBanner is not None:
            self.banner = customBanner

        self.font_size = 6
        self.kernel_manager = kernel_manager = QtInProcessKernelManager()
        kernel_manager.start_kernel(show_banner=False)
        kernel_manager.kernel.gui = 'qt'
        self.kernel_client = kernel_client = self._kernel_manager.client()
        kernel_client.start_channels()

        self.push_vars(namespace)

        def stop():
            kernel_client.stop_channels()
            kernel_manager.shutdown_kernel()
            guisupport.get_app_qt().exit()

        self.exit_requested.connect(stop)

    def push_vars(self, variableDict):
        """
        Given a dictionary containing name / value pairs, push those variables
        to the Jupyter console widget
        """
        self.kernel_manager.kernel.shell.push(variableDict)

    def clear(self):
        """
        Clears the terminal
        """
        self._control.clear()

        # self.kernel_manager

    def print_text(self, text):
        """
        Prints some plain text to the console
        """
        self._append_plain_text(text)

    def execute_command(self, command):
        """
        Execute a command in the frame of the console widget
        """
        self._execute(command, False)


if __name__ == '__main__':
    app = QtGui.QApplication([])
    widget = ConsoleWidget()
    widget.show()
    app.exec_()

Upvotes: 5

Views: 1133

Answers (0)

Related Questions