我想将ipython qtconsole放在MDI pyqt应用程序中作为子窗口,然后从qtconsole创建其他子窗口。因此,嵌入式qtconsole需要能够访问应用程序的名称空间。根据ipython文档中的this page,InProcessKernel将是最佳解决方案。我从python终端运行了this example script(如下所示)(如果从ipython运行它,则会收到MultipleInstanceError)。但是暂时不要创建子窗口,首先,我需要弄清楚如何将对象传递到嵌入式qtconsole中。


我第一次运行inprocess_qtconsole.py时,嵌入式qtconsole的名称空间为空。为什么先前在初始python终端或脚本中创建的对象不会传递给嵌入式qtconsole?
如果关闭包含嵌入式qtconsole的应用程序,在初始终端中定义一些变量,然后再次运行脚本,为什么现在可以访问这些变量以及if __name__ == __main__下脚本中的变量?
有没有一种方法可以启动嵌入式qtconsole而不阻止我从中启动的python终端?


我主要只是希望能够将QMainWindow实例传递到嵌入式qtconsole中,因为创建子窗口需要传递该对象(例如window.mdiArea.addSubWindow()之类的东西)。如果我两次运行脚本,它的工作方式会有些怪异。

顺便说一下,最新版本的ipython中似乎缺少其他官方ipython示例之一(ipkernel_qtapp.py)中使用的internal_ipkernel模块。

运行Python 2.7,IPython 2.2 / 2.3和Windows 8.1。

from __future__ import print_function
import os

from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager
from IPython.lib import guisupport


def print_process_id():
    print('Process ID is:', os.getpid())


def main():
    # Print the ID of the main process
    print_process_id()

    app = guisupport.get_app_qt4()

    # Create an in-process kernel
    # >>> print_process_id()
    # will print the same process ID as the main process
    kernel_manager = QtInProcessKernelManager()
    kernel_manager.start_kernel()
    kernel = kernel_manager.kernel
    kernel.gui = 'qt4'
    kernel.shell.push({'foo': 43, 'print_process_id': print_process_id})

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

    def stop():
        kernel_client.stop_channels()
        kernel_manager.shutdown_kernel()
        app.exit()

    control = RichIPythonWidget()
    control.kernel_manager = kernel_manager
    control.kernel_client = kernel_client
    control.exit_requested.connect(stop)
    control.show()

    guisupport.start_event_loop_qt4(app)


if __name__ == '__main__':
    test = 'hello'
    main()

最佳答案

您可以使用它在给定的qt小部件中启动ipython控制台:

from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager

def put_ipy(parent):
    kernel_manager = QtInProcessKernelManager()
    kernel_manager.start_kernel()
    kernel = kernel_manager.kernel
    kernel.gui = 'qt4'

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

    def stop():
        kernel_client.stop_channels()
        kernel_manager.shutdown_kernel()

    layout = QtGui.QVBoxLayout(parent)
    widget = RichIPythonWidget(parent=parent)
    layout.addWidget(widget)
    widget.kernel_manager = kernel_manager
    widget.kernel_client = kernel_client
    widget.exit_requested.connect(stop)
    ipython_widget = widget
    ipython_widget.show()
    kernel.shell.push({'widget':widget,'kernel':kernel, 'parent':parent})
    return {'widget':widget,'kernel':kernel}


要从控制台弹出窗口,可以运行

app = QtGui.QApplication([])
win = QtGui.QWidget(None)
win.show()
put_ipy(win)


但这会将原来的python解释器换成一个空的ipy解释器,只带有您传递的已定义变量(widget,kernel,parent在这里),即控制台和命令行具有相同的内核,而原始的是受阻。

通过在带有另一个主窗口和一组交互的qt应用程序中执行上述操作,可以避免这种行为。要将变量传递给内核,请使用(如上所述)kernel.shell.push(dict)

关于python - 嵌入ipython qtconsole并传递对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26666583/

10-12 18:17