从iPython/Jupyter嵌入式Qt控制台获取结果对象

Ism*_*sma 6 python python-3.x pyqt5 jupyter jupyter-console

我在使用此处RichJupyterWidget提供的小部件实现的PyQt5应用程序中有一个嵌入式Jupyter控制台.

控制台集成本身工作正常,Jupyter控制台嵌入在Widget中,Python代码可以执行,结果显示在控制台本身.

但是,我需要做的是每当我运行一些返回Pandas的代码时, DataFrame它会在TableView控制台外部显示它.

这是我的实现的一个工作示例:

import sys

from PyQt5.QtWidgets import QMainWindow, QApplication
from qtconsole.inprocess import QtInProcessKernelManager
from qtconsole.rich_jupyter_widget import RichJupyterWidget


class IPythonConsole:

    def __init__(self):
        self._kernel_manager = None
        self._kernel = None
        self._kernel_client = None

        self.start()

    @property
    def kernel_manager(self) -> QtInProcessKernelManager:
        return self._kernel_manager

    @property
    def kernel(self):
        return self._kernel

    @property
    def kernel_client(self):
        return self._kernel_client

    def start(self):
        self._kernel_manager = QtInProcessKernelManager()
        self._kernel_manager.start_kernel()
        self._kernel = self._kernel_manager.kernel
        self._kernel.gui = 'qt'

        self._kernel_client = self._kernel_manager.client()
        self._kernel_client.start_channels()

    def stop(self):
        self._kernel_client.stop_channels()
        self._kernel_manager.shutdown_kernel()


class IPythonWidget(RichJupyterWidget):
    """RichIPythonWidget implementation to integrate the IPython console inside a Qt Widget"""

    def __init__(self):
        super().__init__()

        self._console = IPythonConsole()
        self.kernel_manager = self._console.kernel_manager
        self.kernel_client = self._console.kernel_client

    @property
    def console(self):
        return self._console

    def run_command(self, command_str):
        self.execute(command_str, False, True)

    def close(self):
        self._console.stop()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main_window = QMainWindow()
    ipython_widget = IPythonWidget()
    main_window.layout().addWidget(ipython_widget)
    main_window.setFixedHeight(768)
    main_window.setFixedWidth(1024)

    ipython_widget.run_command("import pandas as pd\n"
                               "df = pd.DataFrame({'Test': ['a', 'b', 'c']})\n"
                               "df")

    main_window.show()

    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

到目前为止,我试图覆盖以下方法RichJupyterWidget:

 def _handle_execute_result(self, msg):
        """Overridden to handle rich data types, like SVG."""
        self.log.debug("execute_result: %s", msg.get('content', ''))
        if self.include_output(msg):
            self.flush_clearoutput()
            content = msg['content']
            prompt_number = content.get('execution_count', 0)
            data = content['data']
            metadata = msg['content']['metadata']
            if 'image/svg+xml' in data:
                self._pre_image_append(msg, prompt_number)
                self._append_svg(data['image/svg+xml'], True)
                self._append_html(self.output_sep2, True)
            elif 'image/png' in data:
            [...]
Run Code Online (Sandbox Code Playgroud)

但不幸的是DataFrame,当返回a时,msg包含一个包含DataFrameHTML格式内容的字符串.

编辑

我能够DataFrame从内核shell 获取对象,如下所示:

if self.ipython_widget.execute("df = pd.DataFrame({'Test': ['a', 'b', 'c']})\n", False, False):
    df = self.ipython_widget.console.kernel.shell.user_ns.get('df')
Run Code Online (Sandbox Code Playgroud)

不幸的是,这仅在我自己运行代码时才起作用,而不是当用户在控制台中输入内容时,我必须知道包含数据帧的变量的名称.