Created
April 24, 2019 20:39
-
-
Save campanelli-resonon/5b4f4a5648f49716e9bf4995d0d3a0fc to your computer and use it in GitHub Desktop.
Creating a Spyder-compatible kernel to run embedded within another Python app using IPython
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Simple function for embedding an IPython kernel.""" | |
import sys | |
from IPython.utils.frame import extract_module_locals | |
import ipykernel.kernelapp | |
from traitlets import Type | |
# Subclass the IPKernelApp, making it point to the SpyderKernel subclass of the IPython kernel. | |
class SpyderKernelApp(ipykernel.kernelapp.IPKernelApp): | |
kernel_class = Type( | |
'spyder_kernels.console.kernel.SpyderKernel', klass='ipykernel.kernelbase.Kernel').tag(config=True) | |
def __init__(self, *args, **kwargs): | |
super(SpyderKernelApp, self).__init__(*args, **kwargs) | |
# This is copy pasta of embed_kernel() from ipykernel's embed.py. | |
def embed_kernel(module=None, local_ns=None, **kwargs): | |
"""Embed and start an IPython kernel in a given scope. | |
Parameters | |
---------- | |
module : ModuleType, optional | |
The module to load into IPython globals (default: caller) | |
local_ns : dict, optional | |
The namespace to load into IPython user namespace (default: caller) | |
kwargs : various, optional | |
Further keyword args are relayed to the IPKernelApp constructor, | |
allowing configuration of the Kernel. Will only have an effect | |
on the first embed_kernel call for a given process. | |
""" | |
# get the app if it exists, or set it up if it doesn't | |
if SpyderKernelApp.initialized(): | |
app = SpyderKernelApp.instance() | |
else: | |
app = SpyderKernelApp.instance(**kwargs) | |
app.initialize([]) | |
# Undo unnecessary sys module mangling from init_sys_modules. | |
# This would not be necessary if we could prevent it | |
# in the first place by using a different InteractiveShell | |
# subclass, as in the regular embed case. | |
main = app.kernel.shell._orig_sys_modules_main_mod | |
if main is not None: | |
sys.modules[app.kernel.shell._orig_sys_modules_main_name] = main | |
# load the calling scope if not given | |
(caller_module, caller_locals) = extract_module_locals(1) | |
if module is None: | |
module = caller_module | |
if local_ns is None: | |
local_ns = caller_locals | |
app.kernel.user_module = module | |
app.kernel.user_ns = local_ns | |
app.shell.set_completer_frame() | |
app.start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment