Embedding IPython Qt console in a PyQt application
Ok, this code seems to do the trick (i.e. it puts a non-blocking ipython interpreter in a Qt widget, which can be embedded into other widgets). Keywords passed to terminal_widget
get added to the namespace of the widget
import atexit
from IPython.zmq.ipkernel import IPKernelApp
from IPython.lib.kernel import find_connection_file
from IPython.frontend.qt.kernelmanager import QtKernelManager
from IPython.frontend.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.utils.traitlets import TraitError
from PyQt4 import QtGui, QtCore
def event_loop(kernel):
kernel.timer = QtCore.QTimer()
kernel.timer.timeout.connect(kernel.do_one_iteration)
kernel.timer.start(1000*kernel._poll_interval)
def default_kernel_app():
app = IPKernelApp.instance()
app.initialize(['python', '--pylab=qt'])
app.kernel.eventloop = event_loop
return app
def default_manager(kernel):
connection_file = find_connection_file(kernel.connection_file)
manager = QtKernelManager(connection_file=connection_file)
manager.load_connection_file()
manager.start_channels()
atexit.register(manager.cleanup_connection_file)
return manager
def console_widget(manager):
try: # Ipython v0.13
widget = RichIPythonWidget(gui_completion='droplist')
except TraitError: # IPython v0.12
widget = RichIPythonWidget(gui_completion=True)
widget.kernel_manager = manager
return widget
def terminal_widget(**kwargs):
kernel_app = default_kernel_app()
manager = default_manager(kernel_app)
widget = console_widget(manager)
#update namespace
kernel_app.shell.user_ns.update(kwargs)
kernel_app.start()
return widget
app = QtGui.QApplication([])
widget = terminal_widget(testing=123)
widget.show()
app.exec_()
Can't quit PyQt5 application with embedded iPython Qtconsole
You have to use a Kernel Manager, like this:
Embedding IPython Qt console in a PyQt application
Here is an working example for PyQt5:
import os
os.environ['QT_API'] = 'pyqt5'
from PyQt5 import QtWidgets
from PyQt5 import QtGui
# ipython won't work if this is not correctly installed. And the error message will be misleading
from PyQt5 import QtSvg
# Import the console machinery from ipython
from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
from IPython.qt.inprocess import QtInProcessKernelManager
def get_app_qt5(*args, **kwargs):
"""Create a new qt5 app or return an existing one."""
app = QtWidgets.QApplication.instance()
if app is None:
if not args:
args = ([''],)
app = QtWidgets.QApplication(*args, **kwargs)
return app
class QIPythonWidget(RichIPythonWidget):
""" Convenience class for a live IPython console widget. We can replace the standard banner using the customBanner argument"""
def __init__(self,customBanner=None,*args,**kwargs):
super(QIPythonWidget, self).__init__(*args,**kwargs)
if customBanner!=None: self.banner=customBanner
self.kernel_manager = kernel_manager = QtInProcessKernelManager()
kernel_manager.start_kernel()
kernel_manager.kernel.gui = 'qt'
self.kernel_client = kernel_client = self._kernel_manager.client()
kernel_client.start_channels()
def stop():
kernel_client.stop_channels()
kernel_manager.shutdown_kernel()
get_app_qt5().exit()
self.exit_requested.connect(stop)
def pushVariables(self,variableDict):
""" Given a dictionary containing name / value pairs, push those variables to the IPython console widget """
self.kernel_manager.kernel.shell.push(variableDict)
def clearTerminal(self):
""" Clears the terminal """
self._control.clear()
def printText(self,text):
""" Prints some plain text to the console """
self._append_plain_text(text)
def executeCommand(self,command):
""" Execute a command in the frame of the console widget """
self._execute(command,False)
class ExampleWidget(QtWidgets.QMainWindow):
""" Main GUI Window including a button and IPython Console widget inside vertical layout """
def __init__(self, parent=None):
super(ExampleWidget, self).__init__(parent)
self.setWindowTitle('iPython in PyQt5 app example')
self.mainWidget = QtWidgets.QWidget(self)
self.setCentralWidget(self.mainWidget)
layout = QtWidgets.QVBoxLayout(self.mainWidget)
self.button = QtWidgets.QPushButton('Another widget')
ipyConsole = QIPythonWidget(customBanner="Welcome to the embedded ipython console\n")
layout.addWidget(self.button)
layout.addWidget(ipyConsole)
# This allows the variable foo and method print_process_id to be accessed from the ipython console
ipyConsole.pushVariables({"foo":43,"print_process_id":print_process_id})
ipyConsole.printText("The variable 'foo' and the method 'print_process_id()' are available. Use the 'whos' command for information.\n\nTo push variables run this before starting the UI:\n ipyConsole.pushVariables({\"foo\":43,\"print_process_id\":print_process_id})")
self.setGeometry(300, 300, 800, 600)
def print_process_id():
print('Process ID is:', os.getpid())
def main():
app = get_app_qt5()
widget = ExampleWidget()
widget.show()
app.exec_()
if __name__ == '__main__':
main()
Embedding Ipython into a PyQt4 App
I went down the same path, but ended up using IPython dev as the embedding solution is cleaner and has no nasty input()
/ help()
bugs.
Here is a work-around for 0.13.x: https://stackoverflow.com/a/12375397/532513 -- problem is, if you use help()
for example, everything freezes.
In the development IPython, it's all much simpler. Here's a working example:
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()
embedding ipython qtconsole and passing objects
You can use this to start an ipython console in a given qt widget:
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}
To pop up windows from the console, you can run
app = QtGui.QApplication([])
win = QtGui.QWidget(None)
win.show()
put_ipy(win)
but this will swap the original python interpreter with an empty ipy one, with only the variables defined that you passed (widget, kernel, parent here), i.e., both the console and the command line have the same kernels, and the original one is blocked.
You can get around such behaviour by doing the above within a qt application with another main window and set of interactions. To pass variables to the kernel, use (as above) kernel.shell.push(dict)
.
Related Topics
How to Create an Object for a Django Model with a Many to Many Field
How to Get Stable Results with Tensorflow, Setting Random Seed
In Python, How to Test If I'm in Google App Engine Sdk
Typeerror: 'List' Object Is Not Callable While Trying to Access a List
Reverse a Get_Dummies Encoding in Pandas
Export a Pandas Dataframe as a Table Image
How to Isolate Everything Inside of a Contour, Scale It, and Test the Similarity to an Image
How to Access a Function Inside a Function
Importerror After Cython Embed
How to Convert a Password into Asterisks While It Is Being Entered
How to Set "Camera Position" for 3D Plots Using Python/Matplotlib