将Ipython嵌入PyQt4应用程序

3
我曾经在 PyQt4 应用程序的测试版阶段将 Python 嵌入其中,并仅在 Ipython 的 git 分支上工作。大约一年前我就没有再看过代码了,自那时以来有很多变化,似乎是在 Ipython 中有很多重构。目前我安装了 13.2 版本。
因此,我需要嵌入 Python 并使其存在于我的 PyQt4 应用程序中,以便可以使用来自我的 Python 应用程序的数据来更改内核的 user_ns。以下是以前针对 git 版本的 python 运行的代码:
import sys
sys.path.insert(0, "../../ipython") #pickup ipython from git in a nonstd dir

from IPython.embedded.ipkernel import EmbeddedKernel
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.frontend.qt.embedded_kernelmanager import QtEmbeddedKernelManager
from IPython.lib import guisupport
from PyQt4.QtGui import QFrame,QHBoxLayout
from PyQt4.QtGui import QApplication
from collections import namedtuple



class IpythonEmbeddedWidget(QFrame):
    def __init__(self):
        QFrame.__init__(self)
        self._layout = QHBoxLayout()
        self._kernel = EmbeddedKernel()
        self._kernel_manager = QtEmbeddedKernelManager(kernel = self._kernel)
        self._kernel_manager.start_channels()
        self._kernel.frontends.append(self._kernel_manager)
        self._shell_widget = RichIPythonWidget()
        app = guisupport.get_app_qt4()
        self._shell_widget.exit_requested.connect(app.quit)
        self._shell_widget.kernel_manager = self._kernel_manager
        self._layout.addWidget(self._shell_widget)
        self.setLayout(self._layout)
        self._kernel.shell.run_cell("import nltk")
        self._kernel.shell.run_cell("import sys")
        self._kernel.shell.run_cell("sys.path.append('../ipython_scripts')")
        self._kernel.shell.run_cell("cd ../ipython_scripts")


    def set_shell_focus(self):
        pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    iew = IpythonEmbeddedWidget()
    iew.show()
    app.exec_()
    sys.exit()

那么,我需要改变什么才能使它与当前(13.2)版本的Ipython兼容?

编辑:

13.2版本没有inprocess-kernel功能。你仍然需要开发分支。我提出这个问题的原因不是因为我更新了我的开发分支,而是在我的电脑上更新QT/PyQt4导致现有代码出现问题。随后我更新了Ipython的开发版本,这要求我重构代码,因为API已经改变。

2个回答

2
我曾经走过同样的路,但最终选择使用IPython dev作为嵌入解决方案,因为它更加清晰,没有令人讨厌的/错误。
对于0.13.x版本,以下是一种解决方法:https://dev59.com/yWgu5IYBdhLWcg3wLEM9#12375397 -- 问题是,如果你使用,例如,所有东西都会被冻结。
在开发版的IPython中,一切都更加简单。以下是一个可行的示例:
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.frontend.qt.inprocess import QtInProcessKernelManager
from IPython.lib import guisupport
from PyQt4.QtGui import QApplication

app = QApplication(sys.argv)

kernel_manager = QtInProcessKernelManager()
kernel_manager.start_kernel()
kernel = kernel_manager.kernel
kernel.gui = 'qt4'

kernel_client = kernel_manager.client()
kernel_client.start_channels()

def stop():
    kernel_client.stop_channels()
    kernel_manager.shutdown_kernel()
    # here you should exit your application with a suitable call
    sys.exit()

widget = RichIPythonWidget()
widget.kernel_manager = kernel_manager
widget.kernel_client = kernel_client
widget.exit_requested.connect(stop)
widget.setWindowTitle("IPython shell")

ipython_widget = widget
ipython_widget.show()

app.exec_()
sys.exit()

这是正确的做法,因为0.13.2没有内置模块。 - Carlos Cordoba
这个code可以运行。但是当我运行代码时,从ipython的git版本中出现了错误。有什么线索吗?我使用的是OS X,并且使用QT(4.8.4)和PyQt4(4.10.1)。 - Hassan Syed
我看到了问题。您正在加载PyQt4 API版本1(Python 2上的默认版本)。在缺少QT_API环境变量的情况下,IPython加载代码尝试使用PySide,然后是PyQt4 API版本2。在您的情况下,它找到了PyQt4 2,但这与您已经加载的1不匹配。要解决问题,请将您的PyQt4导入代码更改为以下内容: import sip; sip.setapi('QString', 2); from PyQt4.QtGui import QApplication - Charl Botha
这在1.1.0版本中有效,但是我认为最好链接到Github树中的新示例(https://github.com/ipython/ipython/blob/master/examples/inprocess/embedded_qtconsole.py)。我在相关问题的解答中提供了稍微详细一些的回答(https://dev59.com/yWgu5IYBdhLWcg3wLEM9#20610786)。 - Tim Rae

0

这是我制作的东西,已经在PyQt4和PySide应用程序中使用QIPythonWidget。我没有对IPython做任何工作,只是对它进行了一些修改,所以可能有更好的方法来完成它,但这个方法有效,并且我没有遇到任何问题。希望能帮到你。


1
我发现这是在IPython 0.13.1中非常有用的方法,但不幸的是它不能在更新的版本中使用。官方示例适用于IPython 1.1.0+。 - Tim Rae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接