##// END OF EJS Templates
Fix tiny typo in demo example
Fix tiny typo in demo example

File last commit:

r2888:5c985e75
r2904:0a827763
Show More
entry_point.py
199 lines | 6.8 KiB | text/x-python | PythonLexer
epatters
* Restored functionality after major merge....
r2778 """ Defines helper functions for creating kernel entry points and process
launchers.
"""
# Standard library imports.
Brian Granger
Merge branch 'newkernel' into upstream-newkernel...
r2873 import os
epatters
* Restored functionality after major merge....
r2778 import socket
from subprocess import Popen
import sys
# System library imports.
import zmq
# Local imports.
Fernando Perez
Install kernel-side sys.excepthook so we at least see kernel tracebacks.
r2853 from IPython.core.ultratb import FormattedTB
epatters
* Restored functionality after major merge....
r2778 from IPython.external.argparse import ArgumentParser
Fernando Perez
Install kernel-side sys.excepthook so we at least see kernel tracebacks.
r2853 from IPython.utils import io
epatters
* Restored functionality after major merge....
r2778 from exitpoller import ExitPollerUnix, ExitPollerWindows
from displayhook import DisplayHook
from iostream import OutStream
from session import Session
def bind_port(socket, ip, port):
""" Binds the specified ZMQ socket. If the port is zero, a random port is
chosen. Returns the port that was bound.
"""
connection = 'tcp://%s' % ip
if port <= 0:
port = socket.bind_to_random_port(connection)
else:
connection += ':%i' % port
socket.bind(connection)
return port
def make_argument_parser():
""" Creates an ArgumentParser for the generic arguments supported by all
kernel entry points.
"""
parser = ArgumentParser()
parser.add_argument('--ip', type=str, default='127.0.0.1',
help='set the kernel\'s IP address [default: local]')
parser.add_argument('--xrep', type=int, metavar='PORT', default=0,
help='set the XREP channel port [default: random]')
parser.add_argument('--pub', type=int, metavar='PORT', default=0,
help='set the PUB channel port [default: random]')
parser.add_argument('--req', type=int, metavar='PORT', default=0,
help='set the REQ channel port [default: random]')
if sys.platform == 'win32':
parser.add_argument('--parent', type=int, metavar='HANDLE',
default=0, help='kill this process if the process '
'with HANDLE dies')
else:
parser.add_argument('--parent', action='store_true',
help='kill this process if its parent dies')
return parser
epatters
Merge branch 'newkernel' of git://github.com/ellisonbg/ipython into qtfrontend...
r2795 def make_kernel(namespace, kernel_factory,
out_stream_factory=None, display_hook_factory=None):
epatters
* Restored functionality after major merge....
r2778 """ Creates a kernel.
"""
Fernando Perez
Install kernel-side sys.excepthook so we at least see kernel tracebacks.
r2853 # Install minimal exception handling
epatters
Removed ANSI coloring for kernel exception hook.
r2888 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
ostream=sys.__stdout__)
Fernando Perez
Install kernel-side sys.excepthook so we at least see kernel tracebacks.
r2853
epatters
* Restored functionality after major merge....
r2778 # Create a context, a session, and the kernel sockets.
Fernando Perez
Update production code to public names of raw_print functions.
r2875 io.raw_print("Starting the kernel...")
epatters
* Restored functionality after major merge....
r2778 context = zmq.Context()
session = Session(username=u'kernel')
reply_socket = context.socket(zmq.XREP)
xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep)
Fernando Perez
Update production code to public names of raw_print functions.
r2875 io.raw_print("XREP Channel on port", xrep_port)
epatters
* Restored functionality after major merge....
r2778
pub_socket = context.socket(zmq.PUB)
pub_port = bind_port(pub_socket, namespace.ip, namespace.pub)
Fernando Perez
Update production code to public names of raw_print functions.
r2875 io.raw_print("PUB Channel on port", pub_port)
epatters
* Restored functionality after major merge....
r2778
req_socket = context.socket(zmq.XREQ)
req_port = bind_port(req_socket, namespace.ip, namespace.req)
Fernando Perez
Update production code to public names of raw_print functions.
r2875 io.raw_print("REQ Channel on port", req_port)
epatters
* Restored functionality after major merge....
r2778
# Redirect input streams and set a display hook.
epatters
Merge branch 'newkernel' of git://github.com/ellisonbg/ipython into qtfrontend...
r2795 if out_stream_factory:
Brian Granger
Merge branch 'newkernel' into upstream-newkernel...
r2873 pass
epatters
Merge branch 'newkernel' of git://github.com/ellisonbg/ipython into qtfrontend...
r2795 sys.stdout = out_stream_factory(session, pub_socket, u'stdout')
sys.stderr = out_stream_factory(session, pub_socket, u'stderr')
if display_hook_factory:
sys.displayhook = display_hook_factory(session, pub_socket)
epatters
* Restored functionality after major merge....
r2778
# Create the kernel.
return kernel_factory(session=session, reply_socket=reply_socket,
pub_socket=pub_socket, req_socket=req_socket)
def start_kernel(namespace, kernel):
""" Starts a kernel.
"""
# Configure this kernel/process to die on parent termination, if necessary.
if namespace.parent:
if sys.platform == 'win32':
poller = ExitPollerWindows(namespace.parent)
else:
poller = ExitPollerUnix()
poller.start()
# Start the kernel mainloop.
kernel.start()
def make_default_main(kernel_factory):
""" Creates the simplest possible kernel entry point.
"""
def main():
namespace = make_argument_parser().parse_args()
epatters
Merge branch 'newkernel' of git://github.com/ellisonbg/ipython into qtfrontend...
r2795 kernel = make_kernel(namespace, kernel_factory, OutStream, DisplayHook)
epatters
* Restored functionality after major merge....
r2778 start_kernel(namespace, kernel)
return main
def base_launch_kernel(code, xrep_port=0, pub_port=0, req_port=0,
independent=False, extra_arguments=[]):
""" Launches a localhost kernel, binding to the specified ports.
Parameters
----------
code : str,
A string of Python code that imports and executes a kernel entry point.
xrep_port : int, optional
The port to use for XREP channel.
pub_port : int, optional
The port to use for the SUB channel.
req_port : int, optional
The port to use for the REQ (raw input) channel.
independent : bool, optional (default False)
If set, the kernel process is guaranteed to survive if this process
dies. If not set, an effort is made to ensure that the kernel is killed
when this process dies. Note that in this case it is still good practice
to kill kernels manually before exiting.
extra_arguments = list, optional
A list of extra arguments to pass when executing the launch code.
Returns
-------
A tuple of form:
(kernel_process, xrep_port, pub_port, req_port)
where kernel_process is a Popen object and the ports are integers.
"""
# Find open ports as necessary.
ports = []
ports_needed = int(xrep_port <= 0) + int(pub_port <= 0) + int(req_port <= 0)
for i in xrange(ports_needed):
sock = socket.socket()
sock.bind(('', 0))
ports.append(sock)
for i, sock in enumerate(ports):
port = sock.getsockname()[1]
sock.close()
ports[i] = port
if xrep_port <= 0:
xrep_port = ports.pop(0)
if pub_port <= 0:
pub_port = ports.pop(0)
if req_port <= 0:
req_port = ports.pop(0)
# Build the kernel launch command.
arguments = [ sys.executable, '-c', code, '--xrep', str(xrep_port),
'--pub', str(pub_port), '--req', str(req_port) ]
arguments.extend(extra_arguments)
# Spawn a kernel.
if independent:
if sys.platform == 'win32':
proc = Popen(['start', '/b'] + arguments, shell=True)
else:
proc = Popen(arguments, preexec_fn=lambda: os.setsid())
else:
if sys.platform == 'win32':
from _subprocess import DuplicateHandle, GetCurrentProcess, \
DUPLICATE_SAME_ACCESS
pid = GetCurrentProcess()
handle = DuplicateHandle(pid, pid, pid, 0,
True, # Inheritable by new processes.
DUPLICATE_SAME_ACCESS)
proc = Popen(arguments + ['--parent', str(int(handle))])
else:
proc = Popen(arguments + ['--parent'])
return proc, xrep_port, pub_port, req_port