diff --git a/IPython/kernel/__init__.py b/IPython/kernel/__init__.py index daa15d1..0735425 100644 --- a/IPython/kernel/__init__.py +++ b/IPython/kernel/__init__.py @@ -6,6 +6,6 @@ from . import zmq from .connect import * from .launcher import * from .client import KernelClient -from .manager import KernelManager +from .manager import KernelManager, run_kernel from .blocking import BlockingKernelClient from .multikernelmanager import MultiKernelManager diff --git a/IPython/kernel/manager.py b/IPython/kernel/manager.py index 9dcef8c..dda0dbe 100644 --- a/IPython/kernel/manager.py +++ b/IPython/kernel/manager.py @@ -5,12 +5,17 @@ from __future__ import absolute_import +from contextlib import contextmanager import os import re import signal import sys import time import warnings +try: + from queue import Empty # Py 3 +except ImportError: + from Queue import Empty # Py 2 import zmq @@ -410,3 +415,39 @@ class KernelManager(ConnectionFileMixin): KernelManagerABC.register(KernelManager) + +def start_new_kernel(startup_timeout=60, kernel_name='python', **kwargs): + """Start a new kernel, and return its Manager and Client""" + km = KernelManager(kernel_name=kernel_name) + km.start_kernel(**kwargs) + kc = km.client() + kc.start_channels() + + kc.kernel_info() + kc.get_shell_msg(block=True, timeout=startup_timeout) + + # Flush channels + for channel in (kc.shell_channel, kc.iopub_channel): + while True: + try: + channel.get_msg(block=True, timeout=0.1) + except Empty: + break + return km, kc + +@contextmanager +def run_kernel(**kwargs): + """Context manager to create a kernel in a subprocess. + + The kernel is shut down when the context exits. + + Returns + ------- + kernel_client: connected KernelClient instance + """ + km, kc = start_new_kernel(**kwargs) + try: + yield kc + finally: + kc.stop_channels() + km.shutdown_kernel(now=True) diff --git a/IPython/kernel/tests/utils.py b/IPython/kernel/tests/utils.py index 3ba288d..8cc4ef2 100644 --- a/IPython/kernel/tests/utils.py +++ b/IPython/kernel/tests/utils.py @@ -15,7 +15,7 @@ except ImportError: import nose import nose.tools as nt -from IPython.kernel import KernelManager +from IPython.kernel import manager #------------------------------------------------------------------------------- # Globals @@ -30,22 +30,13 @@ KC = None #------------------------------------------------------------------------------- # code #------------------------------------------------------------------------------- - - -def start_new_kernel(argv=None): - """start a new kernel, and return its Manager and Client""" - km = KernelManager() - kwargs = dict(stdout=nose.iptest_stdstreams_fileno(), stderr=STDOUT) - if argv: - kwargs['extra_arguments'] = argv - km.start_kernel(**kwargs) - kc = km.client() - kc.start_channels() +def start_new_kernel(**kwargs): + """start a new kernel, and return its Manager and Client - msg_id = kc.kernel_info() - kc.get_shell_msg(block=True, timeout=STARTUP_TIMEOUT) - flush_channels(kc) - return km, kc + Integrates with our output capturing for tests. + """ + kwargs.update(dict(stdout=nose.iptest_stdstreams_fileno(), stderr=STDOUT)) + return manager.start_new_kernel(startup_timeout=STARTUP_TIMEOUT, **kwargs) def flush_channels(kc=None): """flush any messages waiting on the queue""" @@ -121,7 +112,6 @@ def stop_global_kernel(): KM.shutdown_kernel(now=True) KM = None -@contextmanager def new_kernel(argv=None): """Context manager for a new kernel in a subprocess @@ -131,13 +121,11 @@ def new_kernel(argv=None): ------- kernel_client: connected KernelClient instance """ - km, kc = start_new_kernel(argv) - try: - yield kc - finally: - kc.stop_channels() - km.shutdown_kernel(now=True) - + kwargs = dict(stdout=nose.iptest_stdstreams_fileno(), stderr=STDOUT, + startup_timeout=STARTUP_TIMEOUT) + if argv is not None: + kwargs['extra_arguments'] = argv + return manager.run_kernel(**kwargs) def assemble_output(iopub): """assemble stdout/err from an execution"""