PyQt应用程序中的非阻塞IPython Qt控制台

PyQt应用程序中的非阻塞IPython Qt控制台,python,pyqt,pyqt5,ipython,qtconsole,Python,Pyqt,Pyqt5,Ipython,Qtconsole,我希望使用RichJupyterWidget在我的应用程序中嵌入IPython Qt控制台。 对于如何设置控制台,我似乎有两种选择: 使用QtInProcessKernelManager(如下所示)。在这种情况下,内核在执行代码时会阻塞,这是不理想的,因为我希望用户运行某些命令需要花费一分钟的时间 使用QtKernelManager(如下所示)创建作为子进程启动的普通IPython内核。在这种情况下,我无法将名称空间从主进程传递到内核,内核也无法与主应用程序通信。这两项都是要求 这里有可能做到两

我希望使用
RichJupyterWidget
在我的应用程序中嵌入IPython Qt控制台。 对于如何设置控制台,我似乎有两种选择:

  • 使用
    QtInProcessKernelManager
    (如下所示)。在这种情况下,内核在执行代码时会阻塞,这是不理想的,因为我希望用户运行某些命令需要花费一分钟的时间
  • 使用
    QtKernelManager
    (如下所示)创建作为子进程启动的普通IPython内核。在这种情况下,我无法将名称空间从主进程传递到内核,内核也无法与主应用程序通信。这两项都是要求
  • 这里有可能做到两全其美吗?我希望有一个非阻塞控制台,它包含与主进程相同的名称空间,并且可以向主应用程序发送信号。 评论中也提出了类似的问题。将
    QThread
    QtInProcessKernelManager
    一起使用是可能的,但我不确定应该使用什么方法执行线程

    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_()
    

    这可能不是一个优雅的解决方案,但是可以重载RichJupyterWidget的函数_execute,并在一个新线程中执行所有命令。这样,应用程序的其余部分就不会阻塞。