##// END OF EJS Templates
Merge pull request #6110 from minrk/binarycomm...
Merge pull request #6110 from minrk/binarycomm support binary buffers in comm messages

File last commit:

r18309:ddc05938 merge
r18418:2a8a2c87 merge
Show More
kernelapp.py
391 lines | 14.8 KiB | text/x-python | PythonLexer
MinRK
pyerr -> error
r16569 """An Application for launching a kernel"""
Paul Ivanov
remove load_connection_file from kernelapp...
r16501 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
MinRK
zmq kernels now started via newapp
r3970
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 from __future__ import print_function
MinRK
kernel app cleans up connection files that it wrote
r6889 import atexit
MinRK
zmq kernels now started via newapp
r3970 import os
import sys
MinRK
use IOLoop in ipkernel...
r6790 import signal
MinRK
zmq kernels now started via newapp
r3970
import zmq
MinRK
use IOLoop in ipkernel...
r6790 from zmq.eventloop import ioloop
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 from zmq.eventloop.zmqstream import ZMQStream
MinRK
zmq kernels now started via newapp
r3970
from IPython.core.ultratb import FormattedTB
MinRK
rename core.newapplication -> core.application
r4023 from IPython.core.application import (
MinRK
catch_config -> catch_config_error
r5214 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
MinRK
zmq kernels now started via newapp
r3970 )
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 from IPython.core.profiledir import ProfileDir
from IPython.core.shellapp import (
InteractiveShellApp, shell_flags, shell_aliases
)
MinRK
zmq kernels now started via newapp
r3970 from IPython.utils import io
MinRK
use connection files instead of ports to connect to kernels...
r4958 from IPython.utils.path import filefind
MinRK
enable IPC transport for kernels...
r7321 from IPython.utils.traitlets import (
Thomas Kluyver
Document how to create wrapper kernels
r16859 Any, Instance, Dict, Unicode, Integer, Bool, DottedObjectName, Type,
MinRK
enable IPC transport for kernels...
r7321 )
MinRK
zmq kernels now started via newapp
r3970 from IPython.utils.importstring import import_item
MinRK
move utils.kernel (formerly entry_point and lib.kernel) to kernel.util
r9353 from IPython.kernel import write_connection_file
Paul Ivanov
remove load_connection_file from kernelapp...
r16501 from IPython.kernel.connect import ConnectionFileMixin
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357
MinRK
zmq kernels now started via newapp
r3970 # local imports
Thomas Kluyver
Use explicit relative imports...
r13347 from .heartbeat import Heartbeat
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 from .ipkernel import IPythonKernel
Thomas Kluyver
Use explicit relative imports...
r13347 from .parentpoller import ParentPollerUnix, ParentPollerWindows
from .session import (
MinRK
enable HMAC message signing by default in kernels...
r4962 Session, session_flags, session_aliases, default_secure,
)
Thomas Kluyver
Use explicit relative imports...
r13347 from .zmqshell import ZMQInteractiveShell
MinRK
zmq kernels now started via newapp
r3970
#-----------------------------------------------------------------------------
# Flags and Aliases
#-----------------------------------------------------------------------------
kernel_aliases = dict(base_aliases)
kernel_aliases.update({
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 'ip' : 'IPKernelApp.ip',
'hb' : 'IPKernelApp.hb_port',
'shell' : 'IPKernelApp.shell_port',
'iopub' : 'IPKernelApp.iopub_port',
'stdin' : 'IPKernelApp.stdin_port',
MinRK
add control channel...
r10296 'control' : 'IPKernelApp.control_port',
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 'f' : 'IPKernelApp.connection_file',
MinRK
use `parent=self` throughout IPython...
r11064 'parent': 'IPKernelApp.parent_handle',
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 'transport': 'IPKernelApp.transport',
MinRK
zmq kernels now started via newapp
r3970 })
if sys.platform.startswith('win'):
MinRK
fix a few remaining KernelApp/IPKernelApp changes
r9516 kernel_aliases['interrupt'] = 'IPKernelApp.interrupt'
MinRK
zmq kernels now started via newapp
r3970
kernel_flags = dict(base_flags)
kernel_flags.update({
'no-stdout' : (
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 {'IPKernelApp' : {'no_stdout' : True}},
MinRK
zmq kernels now started via newapp
r3970 "redirect stdout to the null device"),
'no-stderr' : (
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 {'IPKernelApp' : {'no_stderr' : True}},
MinRK
zmq kernels now started via newapp
r3970 "redirect stderr to the null device"),
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 'pylab' : (
{'IPKernelApp' : {'pylab' : 'auto'}},
"""Pre-load matplotlib and numpy for interactive use with
the default matplotlib backend."""),
MinRK
zmq kernels now started via newapp
r3970 })
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 # inherit flags&aliases for any IPython shell apps
kernel_aliases.update(shell_aliases)
kernel_flags.update(shell_flags)
MinRK
enable HMAC message signing by default in kernels...
r4962 # inherit flags&aliases for Sessions
kernel_aliases.update(session_aliases)
kernel_flags.update(session_flags)
Paul Ivanov
document Ctrl-C not working in ipython kernel...
r11654 _ctrl_c_message = """\
NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.
To exit, you will have to explicitly quit this process, by either sending
"quit" from a client, or using Ctrl-\\ in UNIX-like environments.
To read more about this, see https://github.com/ipython/ipython/issues/2049
"""
MinRK
zmq kernels now started via newapp
r3970 #-----------------------------------------------------------------------------
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 # Application class for starting an IPython Kernel
MinRK
zmq kernels now started via newapp
r3970 #-----------------------------------------------------------------------------
Paul Ivanov
remove load_connection_file from kernelapp...
r16501 class IPKernelApp(BaseIPythonApplication, InteractiveShellApp,
ConnectionFileMixin):
MinRK
ipython_kernel gets its own config file
r17961 name='ipython-kernel'
MinRK
zmq kernels now started via newapp
r3970 aliases = Dict(kernel_aliases)
flags = Dict(kernel_flags)
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 classes = [IPythonKernel, ZMQInteractiveShell, ProfileDir, Session]
MinRK
zmq kernels now started via newapp
r3970 # the kernel class, as an importstring
Thomas Kluyver
Rename KernelBase & Kernel to Kernel & IPythonKernel
r17095 kernel_class = Type('IPython.kernel.zmq.ipkernel.IPythonKernel', config=True,
klass='IPython.kernel.zmq.kernelbase.Kernel',
MinRK
actually use IPKernelApp.kernel_class...
r10046 help="""The Kernel subclass to be used.
This should allow easy re-use of the IPKernelApp entry point
to configure and launch kernels other than IPython's own.
""")
MinRK
zmq kernels now started via newapp
r3970 kernel = Any()
poller = Any() # don't restrict this even though current pollers are all Threads
heartbeat = Instance(Heartbeat)
ports = Dict()
MinRK
add config file inheritance to kernelapp...
r4118
MinRK
zmq kernels now started via newapp
r3970 # connection info:
MinRK
use connection files instead of ports to connect to kernels...
r4958
MinRK
improve default ipc file locations...
r9175 @property
def abs_connection_file(self):
if os.path.basename(self.connection_file) == self.connection_file:
return os.path.join(self.profile_dir.security_dir, self.connection_file)
else:
return self.connection_file
MinRK
zmq kernels now started via newapp
r3970
# streams, etc.
no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 outstream_class = DottedObjectName('IPython.kernel.zmq.iostream.OutStream',
Thomas Kluyver
Use DottedObjectName traits in zmq and parallel modules.
r4055 config=True, help="The importstring for the OutStream factory")
MinRK
mv IPython.zmq to IPython.kernel.zmq
r9372 displayhook_class = DottedObjectName('IPython.kernel.zmq.displayhook.ZMQDisplayHook',
Thomas Kluyver
Use DottedObjectName traits in zmq and parallel modules.
r4055 config=True, help="The importstring for the DisplayHook factory")
MinRK
zmq kernels now started via newapp
r3970
# polling
MinRK
use `parent=self` throughout IPython...
r11064 parent_handle = Integer(0, config=True,
MinRK
zmq kernels now started via newapp
r3970 help="""kill this process if its parent dies. On Windows, the argument
specifies the HANDLE of the parent process, otherwise it is simply boolean.
""")
MinRK
add Integer traitlet...
r5344 interrupt = Integer(0, config=True,
MinRK
zmq kernels now started via newapp
r3970 help="""ONLY USED ON WINDOWS
MinRK
improve default ipc file locations...
r9175 Interrupt this process when the parent is signaled.
MinRK
zmq kernels now started via newapp
r3970 """)
def init_crash_handler(self):
# Install minimal exception handling
sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
ostream=sys.__stdout__)
def init_poller(self):
if sys.platform == 'win32':
MinRK
use `parent=self` throughout IPython...
r11064 if self.interrupt or self.parent_handle:
self.poller = ParentPollerWindows(self.interrupt, self.parent_handle)
elif self.parent_handle:
MinRK
zmq kernels now started via newapp
r3970 self.poller = ParentPollerUnix()
def _bind_socket(self, s, port):
MinRK
enable IPC transport for kernels...
r7321 iface = '%s://%s' % (self.transport, self.ip)
MinRK
improve default ipc file locations...
r9175 if self.transport == 'tcp':
if port <= 0:
port = s.bind_to_random_port(iface)
else:
s.bind("tcp://%s:%i" % (self.ip, port))
elif self.transport == 'ipc':
if port <= 0:
MinRK
don't limit ports to 1024
r9243 port = 1
path = "%s-%i" % (self.ip, port)
while os.path.exists(path):
port = port + 1
MinRK
improve default ipc file locations...
r9175 path = "%s-%i" % (self.ip, port)
else:
path = "%s-%i" % (self.ip, port)
s.bind("ipc://%s" % path)
MinRK
zmq kernels now started via newapp
r3970 return port
MinRK
use connection files instead of ports to connect to kernels...
r4958 def write_connection_file(self):
"""write connection info to JSON file"""
MinRK
improve default ipc file locations...
r9175 cf = self.abs_connection_file
self.log.debug("Writing connection file: %s", cf)
MinRK
enable IPC transport for kernels...
r7321 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
MinRK
use connection files instead of ports to connect to kernels...
r4958 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
MinRK
add control channel...
r10296 iopub_port=self.iopub_port, control_port=self.control_port)
MinRK
kernel app cleans up connection files that it wrote
r6889
def cleanup_connection_file(self):
MinRK
improve default ipc file locations...
r9175 cf = self.abs_connection_file
self.log.debug("Cleaning up connection file: %s", cf)
MinRK
kernel app cleans up connection files that it wrote
r6889 try:
os.remove(cf)
except (IOError, OSError):
pass
MinRK
enable IPC transport for kernels...
r7321
Brian Granger
Fixing bug in cleanup of ipc files and adding new to shutdown....
r9119 self.cleanup_ipc_files()
MinRK
enable IPC transport for kernels...
r7321
MinRK
use connection files instead of ports to connect to kernels...
r4958 def init_connection_file(self):
if not self.connection_file:
self.connection_file = "kernel-%s.json"%os.getpid()
MinRK
protect kernelapp/qtconsole from invalid connection files...
r4986 try:
Paul Ivanov
remove load_connection_file from kernelapp...
r16501 self.connection_file = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
except IOError:
self.log.debug("Connection file not found: %s", self.connection_file)
# This means I own it, so I will clean it up:
atexit.register(self.cleanup_connection_file)
return
try:
MinRK
protect kernelapp/qtconsole from invalid connection files...
r4986 self.load_connection_file()
except Exception:
self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
self.exit(1)
MinRK
enable HMAC message signing by default in kernels...
r4962
MinRK
zmq kernels now started via newapp
r3970 def init_sockets(self):
# Create a context, a session, and the kernel sockets.
MinRK
fix typo in log message format in zmq.kernelapp
r4240 self.log.info("Starting the kernel at pid: %i", os.getpid())
MinRK
zmq kernels now started via newapp
r3970 context = zmq.Context.instance()
# Uncomment this to try closing the context.
# atexit.register(context.term)
MinRK
use ROUTER/DEALER socket names instead of XREP/XREQ...
r4725 self.shell_socket = context.socket(zmq.ROUTER)
MinRK
set linger on every socket I can find...
r16535 self.shell_socket.linger = 1000
MinRK
zmq kernels now started via newapp
r3970 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
MinRK
add control channel...
r10296 self.log.debug("shell ROUTER Channel on port: %i" % self.shell_port)
MinRK
zmq kernels now started via newapp
r3970
self.iopub_socket = context.socket(zmq.PUB)
MinRK
set linger on every socket I can find...
r16535 self.iopub_socket.linger = 1000
MinRK
zmq kernels now started via newapp
r3970 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
MinRK
add control channel...
r10296 self.log.debug("iopub PUB Channel on port: %i" % self.iopub_port)
MinRK
zmq kernels now started via newapp
r3970
MinRK
use ROUTER/DEALER sockets for stdin...
r4952 self.stdin_socket = context.socket(zmq.ROUTER)
MinRK
set linger on every socket I can find...
r16535 self.stdin_socket.linger = 1000
MinRK
zmq kernels now started via newapp
r3970 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
MinRK
add control channel...
r10296 self.log.debug("stdin ROUTER Channel on port: %i" % self.stdin_port)
self.control_socket = context.socket(zmq.ROUTER)
MinRK
set linger on every socket I can find...
r16535 self.control_socket.linger = 1000
MinRK
add control channel...
r10296 self.control_port = self._bind_socket(self.control_socket, self.control_port)
self.log.debug("control ROUTER Channel on port: %i" % self.control_port)
MinRK
split init_sockets into a few steps, so they can be better reused
r6885
def init_heartbeat(self):
"""start the heart beating"""
MinRK
kernel heartbeat does not share zmq context with rest of the app...
r5883 # heartbeat doesn't share context, because it mustn't be blocked
# by the GIL, which is accessed by libzmq when freeing zero-copy messages
hb_ctx = zmq.Context()
MinRK
enable IPC transport for kernels...
r7321 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
MinRK
zmq kernels now started via newapp
r3970 self.hb_port = self.heartbeat.port
MinRK
add control channel...
r10296 self.log.debug("Heartbeat REP Channel on port: %i" % self.hb_port)
MinRK
minor fixes to allow kernel to be re-entrant...
r6826 self.heartbeat.start()
MinRK
split init_sockets into a few steps, so they can be better reused
r6885
def log_connection_info(self):
"""display connection info, and store ports"""
MinRK
fix kernel connection messsage with non-default profile...
r4980 basename = os.path.basename(self.connection_file)
if basename == self.connection_file or \
os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
MinRK
use connection files instead of ports to connect to kernels...
r4958 # use shortname
MinRK
fix kernel connection messsage with non-default profile...
r4980 tail = basename
MinRK
use connection files instead of ports to connect to kernels...
r4958 if self.profile != 'default':
MinRK
fix kernel connection messsage with non-default profile...
r4980 tail += " --profile %s" % self.profile
MinRK
use connection files instead of ports to connect to kernels...
r4958 else:
tail = self.connection_file
MinRK
demote connection info to log.info...
r10563 lines = [
"To connect another client to this kernel, use:",
" --existing %s" % tail,
]
# log connection info
# info-level, so often not shown.
# frontends should use the %connect_info magic
# to see the connection info
for line in lines:
self.log.info(line)
MinRK
use `parent=self` throughout IPython...
r11064 # also raw print to the terminal if no parent_handle (`ipython kernel`)
if not self.parent_handle:
Paul Ivanov
document Ctrl-C not working in ipython kernel...
r11654 io.rprint(_ctrl_c_message)
MinRK
demote connection info to log.info...
r10563 for line in lines:
io.rprint(line)
MinRK
zmq kernels now started via newapp
r3970
self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
MinRK
add control channel...
r10296 stdin=self.stdin_port, hb=self.hb_port,
control=self.control_port)
MinRK
zmq kernels now started via newapp
r3970
Min RK
fix ipython-qtconsole when run as a GUI script
r4112 def init_blackhole(self):
"""redirects stdout/stderr to devnull if necessary"""
MinRK
zmq kernels now started via newapp
r3970 if self.no_stdout or self.no_stderr:
Brandon Parsons
substitute open(...) for file(...)...
r6650 blackhole = open(os.devnull, 'w')
MinRK
zmq kernels now started via newapp
r3970 if self.no_stdout:
sys.stdout = sys.__stdout__ = blackhole
if self.no_stderr:
sys.stderr = sys.__stderr__ = blackhole
Min RK
fix ipython-qtconsole when run as a GUI script
r4112
def init_io(self):
"""Redirect input streams and set a display hook."""
MinRK
zmq kernels now started via newapp
r3970 if self.outstream_class:
outstream_factory = import_item(str(self.outstream_class))
sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
if self.displayhook_class:
displayhook_factory = import_item(str(self.displayhook_class))
sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
MinRK
use IOLoop in ipkernel...
r6790 def init_signal(self):
signal.signal(signal.SIGINT, signal.SIG_IGN)
MinRK
zmq kernels now started via newapp
r3970 def init_kernel(self):
"""Create the Kernel object itself"""
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 shell_stream = ZMQStream(self.shell_socket)
MinRK
add control channel...
r10296 control_stream = ZMQStream(self.control_socket)
MinRK
actually use IPKernelApp.kernel_class...
r10046
Thomas Kluyver
Make comm_manager a property of kernel, not shell
r17987 kernel_factory = self.kernel_class.instance
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357
MinRK
use `parent=self` throughout IPython...
r11064 kernel = kernel_factory(parent=self, session=self.session,
MinRK
add control channel...
r10296 shell_streams=[shell_stream, control_stream],
MinRK
zmq kernels now started via newapp
r3970 iopub_socket=self.iopub_socket,
stdin_socket=self.stdin_socket,
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 log=self.log,
profile_dir=self.profile_dir,
Thomas Kluyver
Fix passing user_ns to IPython.start_kernel()
r12160 user_ns=self.user_ns,
MinRK
zmq kernels now started via newapp
r3970 )
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 kernel.record_ports(self.ports)
self.kernel = kernel
def init_gui_pylab(self):
"""Enable GUI event loop integration, taking pylab into account."""
# Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
# to ensure that any exception is printed straight to stderr.
# Normally _showtraceback associates the reply with an execution,
# which means frontends will never draw it, as this exception
# is not associated with any execute request.
shell = self.shell
_showtraceback = shell._showtraceback
try:
MinRK
pyerr -> error
r16569 # replace error-sending traceback with stderr
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 def print_tb(etype, evalue, stb):
print ("GUI event loop or pylab initialization failed",
file=io.stderr)
print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
shell._showtraceback = print_tb
InteractiveShellApp.init_gui_pylab(self)
finally:
shell._showtraceback = _showtraceback
def init_shell(self):
Thomas Kluyver
Fix some assumptions in kernelapp
r16963 self.shell = getattr(self.kernel, 'shell', None)
if self.shell:
self.shell.configurables.append(self)
MinRK
zmq kernels now started via newapp
r3970
MinRK
catch_config -> catch_config_error
r5214 @catch_config_error
MinRK
zmq kernels now started via newapp
r3970 def initialize(self, argv=None):
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 super(IPKernelApp, self).initialize(argv)
MinRK
add Session to ConnectionFileMixin...
r16731 default_secure(self.config)
Min RK
fix ipython-qtconsole when run as a GUI script
r4112 self.init_blackhole()
MinRK
use connection files instead of ports to connect to kernels...
r4958 self.init_connection_file()
MinRK
zmq kernels now started via newapp
r3970 self.init_poller()
self.init_sockets()
MinRK
split init_sockets into a few steps, so they can be better reused
r6885 self.init_heartbeat()
# writing/displaying connection info must be *after* init_sockets/heartbeat
self.log_connection_info()
MinRK
use connection files instead of ports to connect to kernels...
r4958 self.write_connection_file()
MinRK
zmq kernels now started via newapp
r3970 self.init_io()
MinRK
use IOLoop in ipkernel...
r6790 self.init_signal()
MinRK
zmq kernels now started via newapp
r3970 self.init_kernel()
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357 # shell init steps
self.init_path()
self.init_shell()
Thomas Kluyver
Fix some assumptions in kernelapp
r16963 if self.shell:
self.init_gui_pylab()
self.init_extensions()
self.init_code()
MinRK
flush messages printed during startup...
r5361 # flush stdout/stderr, so that anything written to these streams during
# initialization do not get associated with the first execution request
sys.stdout.flush()
sys.stderr.flush()
MinRK
zmq kernels now started via newapp
r3970
def start(self):
if self.poller is not None:
self.poller.start()
MinRK
use IOLoop in ipkernel...
r6790 self.kernel.start()
MinRK
zmq kernels now started via newapp
r3970 try:
MinRK
use IOLoop in ipkernel...
r6790 ioloop.IOLoop.instance().start()
MinRK
zmq kernels now started via newapp
r3970 except KeyboardInterrupt:
pass
MinRK
code updates per review of PR #454
r4021
Thomas Kluyver
Fix IPython.start_kernel()...
r12158 launch_new_instance = IPKernelApp.launch_instance
MinRK
move IPKernelApp from zmq.ipkernel to zmq.kernelapp...
r9357
def main():
"""Run an IPKernel as an application"""
app = IPKernelApp.instance()
app.initialize()
app.start()
if __name__ == '__main__':
main()