我想在MDI pyqt应用程序中放置一个ipython qtconsole作为子窗口,然后从qtconsole创建其他子窗口。因此,嵌入式qtconsole需要能够访问应用程序的命名空间。根据ipython文档中的这一页,InProcessKernel将是最好的解决方案。我从python终端运行了这个示例脚本(如下所示)(如果我从ipython运行它,我会得到一个MultipleInstanceError)。但现在忘记创建子窗口吧,首先我需要弄清楚如何将对象传递到嵌入式qtconsole中。
- 第一次运行inprocess_qtconsole.py时,嵌入的qtconsole的命名空间为空。为什么以前在初始python终端或脚本中创建的对象没有传递到嵌入式qtconsole
- 如果我关闭包含嵌入式qtconsole的应用程序,在初始终端中定义一些变量,然后再次运行脚本,为什么我现在可以访问这些变量,以及
if __name__ == __main__
下脚本中的变量 - 有没有一种方法可以在不阻塞我启动嵌入式qtconsole的python终端的情况下启动它
我主要只想能够将QMainWindow实例传递到嵌入式qtconsole中,因为创建子窗口需要传递这个对象(类似于window.mdiArea.addSubWindow()
)。如果我运行两次脚本,它的工作方式有点像黑客。
顺便说一句,其他官方ipython示例(ipkernel_qtapp.py)中使用的internal_ipkernel
模块似乎在最新版本的ipython中丢失了。
运行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)
但这将用一个空的ipy解释器替换原始的python解释器,只定义您传递的变量(这里是小部件、内核、父级),即控制台和命令行都有相同的内核,而原始的内核被阻止。
您可以通过在具有另一个主窗口和一组交互的qt应用程序中执行上述操作来绕过这种行为。要将变量传递给内核,请使用(如上所述)kernel.shell.push(dict)
。