##// END OF EJS Templates
adjust embed_kernel signature...
MinRK -
Show More
@@ -1,70 +1,86 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IPython: tools for interactive and parallel computing in Python.
3 IPython: tools for interactive and parallel computing in Python.
4
4
5 http://ipython.org
5 http://ipython.org
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2008-2011, IPython Development Team.
8 # Copyright (c) 2008-2011, IPython Development Team.
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
12 #
12 #
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14 #
14 #
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 from __future__ import absolute_import
21 from __future__ import absolute_import
22
22
23 import os
23 import os
24 import sys
24 import sys
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Setup everything
27 # Setup everything
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 # Don't forget to also update setup.py when this changes!
30 # Don't forget to also update setup.py when this changes!
31 if sys.version[0:3] < '2.6':
31 if sys.version[0:3] < '2.6':
32 raise ImportError('Python Version 2.6 or above is required for IPython.')
32 raise ImportError('Python Version 2.6 or above is required for IPython.')
33
33
34 # Make it easy to import extensions - they are always directly on pythonpath.
34 # Make it easy to import extensions - they are always directly on pythonpath.
35 # Therefore, non-IPython modules can be added to extensions directory.
35 # Therefore, non-IPython modules can be added to extensions directory.
36 # This should probably be in ipapp.py.
36 # This should probably be in ipapp.py.
37 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
37 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Setup the top level names
40 # Setup the top level names
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 from .config.loader import Config
43 from .config.loader import Config
44 from .core import release
44 from .core import release
45 from .core.application import Application
45 from .core.application import Application
46 from .frontend.terminal.embed import embed
46 from .frontend.terminal.embed import embed
47
47
48 from .core.error import TryNext
48 from .core.error import TryNext
49 from .core.interactiveshell import InteractiveShell
49 from .core.interactiveshell import InteractiveShell
50 from .testing import test
50 from .testing import test
51 from .utils.sysinfo import sys_info
51 from .utils.sysinfo import sys_info
52 from .utils.frame import extract_module_locals
52 from .utils.frame import extract_module_locals
53
53
54 # Release data
54 # Release data
55 __author__ = ''
55 __author__ = ''
56 for author, email in release.authors.itervalues():
56 for author, email in release.authors.itervalues():
57 __author__ += author + ' <' + email + '>\n'
57 __author__ += author + ' <' + email + '>\n'
58 __license__ = release.license
58 __license__ = release.license
59 __version__ = release.version
59 __version__ = release.version
60
60
61 def embed_kernel(module=None, local_ns=None):
61 def embed_kernel(module=None, local_ns=None, **kwargs):
62 """Call this to embed an IPython kernel at the current point in your program. """
62 """Embed and start an IPython kernel in a given scope.
63
64 Parameters
65 ----------
66 module : ModuleType, optional
67 The module to load into IPython globals (default: caller)
68 local_ns : dict, optional
69 The namespace to load into IPython user namespace (default: caller)
70
71 kwargs : various, optional
72 Further keyword args are relayed to the KernelApp constructor,
73 allowing configuration of the Kernel. Will only have an effect
74 on the first embed_kernel call for a given process.
75
76 """
77
63 (caller_module, caller_locals) = extract_module_locals(1)
78 (caller_module, caller_locals) = extract_module_locals(1)
64 if module is None:
79 if module is None:
65 module = caller_module
80 module = caller_module
66 if local_ns is None:
81 if local_ns is None:
67 local_ns = caller_locals
82 local_ns = caller_locals
83
68 # Only import .zmq when we really need it
84 # Only import .zmq when we really need it
69 from .zmq.ipkernel import embed_kernel as real_embed_kernel
85 from .zmq.ipkernel import embed_kernel as real_embed_kernel
70 real_embed_kernel(module, local_ns)
86 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
@@ -1,661 +1,700 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports.
18 # Standard library imports.
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25 from signal import (
25 from signal import (
26 signal, default_int_handler, SIGINT, SIG_IGN
26 signal, default_int_handler, SIGINT, SIG_IGN
27 )
27 )
28 # System library imports.
28 # System library imports.
29 import zmq
29 import zmq
30
30
31 # Local imports.
31 # Local imports.
32 from IPython.core import pylabtools
32 from IPython.core import pylabtools
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.config.application import boolean_flag, catch_config_error
34 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.core.application import ProfileDir
35 from IPython.core.application import ProfileDir
36 from IPython.core.error import StdinNotImplementedError
36 from IPython.core.error import StdinNotImplementedError
37 from IPython.core.shellapp import (
37 from IPython.core.shellapp import (
38 InteractiveShellApp, shell_flags, shell_aliases
38 InteractiveShellApp, shell_flags, shell_aliases
39 )
39 )
40 from IPython.utils import io
40 from IPython.utils import io
41 from IPython.utils import py3compat
41 from IPython.utils import py3compat
42 from IPython.utils.frame import extract_module_locals
42 from IPython.utils.jsonutil import json_clean
43 from IPython.utils.jsonutil import json_clean
43 from IPython.utils.traitlets import (
44 from IPython.utils.traitlets import (
44 Any, Instance, Float, Dict, CaselessStrEnum
45 Any, Instance, Float, Dict, CaselessStrEnum
45 )
46 )
46
47
47 from entry_point import base_launch_kernel
48 from entry_point import base_launch_kernel
48 from kernelapp import KernelApp, kernel_flags, kernel_aliases
49 from kernelapp import KernelApp, kernel_flags, kernel_aliases
49 from session import Session, Message
50 from session import Session, Message
50 from zmqshell import ZMQInteractiveShell
51 from zmqshell import ZMQInteractiveShell
51
52
52
53
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
54 # Main kernel class
55 # Main kernel class
55 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
56
57
57 class Kernel(Configurable):
58 class Kernel(Configurable):
58
59
59 #---------------------------------------------------------------------------
60 #---------------------------------------------------------------------------
60 # Kernel interface
61 # Kernel interface
61 #---------------------------------------------------------------------------
62 #---------------------------------------------------------------------------
62
63
63 # attribute to override with a GUI
64 # attribute to override with a GUI
64 eventloop = Any(None)
65 eventloop = Any(None)
65
66
66 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
67 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
67 session = Instance(Session)
68 session = Instance(Session)
68 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
69 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
69 shell_socket = Instance('zmq.Socket')
70 shell_socket = Instance('zmq.Socket')
70 iopub_socket = Instance('zmq.Socket')
71 iopub_socket = Instance('zmq.Socket')
71 stdin_socket = Instance('zmq.Socket')
72 stdin_socket = Instance('zmq.Socket')
72 log = Instance(logging.Logger)
73 log = Instance(logging.Logger)
74
73 user_module = Instance('types.ModuleType')
75 user_module = Instance('types.ModuleType')
76 def _user_module_changed(self, name, old, new):
77 if self.shell is not None:
78 self.shell.user_module = new
79
74 user_ns = Dict(default_value=None)
80 user_ns = Dict(default_value=None)
81 def _user_ns_changed(self, name, old, new):
82 if self.shell is not None:
83 self.shell.user_ns = new
84 self.shell.init_user_ns()
75
85
76 # Private interface
86 # Private interface
77
87
78 # Time to sleep after flushing the stdout/err buffers in each execute
88 # Time to sleep after flushing the stdout/err buffers in each execute
79 # cycle. While this introduces a hard limit on the minimal latency of the
89 # cycle. While this introduces a hard limit on the minimal latency of the
80 # execute cycle, it helps prevent output synchronization problems for
90 # execute cycle, it helps prevent output synchronization problems for
81 # clients.
91 # clients.
82 # Units are in seconds. The minimum zmq latency on local host is probably
92 # Units are in seconds. The minimum zmq latency on local host is probably
83 # ~150 microseconds, set this to 500us for now. We may need to increase it
93 # ~150 microseconds, set this to 500us for now. We may need to increase it
84 # a little if it's not enough after more interactive testing.
94 # a little if it's not enough after more interactive testing.
85 _execute_sleep = Float(0.0005, config=True)
95 _execute_sleep = Float(0.0005, config=True)
86
96
87 # Frequency of the kernel's event loop.
97 # Frequency of the kernel's event loop.
88 # Units are in seconds, kernel subclasses for GUI toolkits may need to
98 # Units are in seconds, kernel subclasses for GUI toolkits may need to
89 # adapt to milliseconds.
99 # adapt to milliseconds.
90 _poll_interval = Float(0.05, config=True)
100 _poll_interval = Float(0.05, config=True)
91
101
92 # If the shutdown was requested over the network, we leave here the
102 # If the shutdown was requested over the network, we leave here the
93 # necessary reply message so it can be sent by our registered atexit
103 # necessary reply message so it can be sent by our registered atexit
94 # handler. This ensures that the reply is only sent to clients truly at
104 # handler. This ensures that the reply is only sent to clients truly at
95 # the end of our shutdown process (which happens after the underlying
105 # the end of our shutdown process (which happens after the underlying
96 # IPython shell's own shutdown).
106 # IPython shell's own shutdown).
97 _shutdown_message = None
107 _shutdown_message = None
98
108
99 # This is a dict of port number that the kernel is listening on. It is set
109 # This is a dict of port number that the kernel is listening on. It is set
100 # by record_ports and used by connect_request.
110 # by record_ports and used by connect_request.
101 _recorded_ports = Dict()
111 _recorded_ports = Dict()
102
112
103
113
104
114
105 def __init__(self, **kwargs):
115 def __init__(self, **kwargs):
106 super(Kernel, self).__init__(**kwargs)
116 super(Kernel, self).__init__(**kwargs)
107
117
108 # Before we even start up the shell, register *first* our exit handlers
118 # Before we even start up the shell, register *first* our exit handlers
109 # so they come before the shell's
119 # so they come before the shell's
110 atexit.register(self._at_shutdown)
120 atexit.register(self._at_shutdown)
111
121
112 # Initialize the InteractiveShell subclass
122 # Initialize the InteractiveShell subclass
113 self.shell = ZMQInteractiveShell.instance(config=self.config,
123 self.shell = ZMQInteractiveShell.instance(config=self.config,
114 profile_dir = self.profile_dir,
124 profile_dir = self.profile_dir,
115 user_module = self.user_module,
125 user_module = self.user_module,
116 user_ns = self.user_ns,
126 user_ns = self.user_ns,
117 )
127 )
118 self.shell.displayhook.session = self.session
128 self.shell.displayhook.session = self.session
119 self.shell.displayhook.pub_socket = self.iopub_socket
129 self.shell.displayhook.pub_socket = self.iopub_socket
120 self.shell.display_pub.session = self.session
130 self.shell.display_pub.session = self.session
121 self.shell.display_pub.pub_socket = self.iopub_socket
131 self.shell.display_pub.pub_socket = self.iopub_socket
122
132
123 # TMP - hack while developing
133 # TMP - hack while developing
124 self.shell._reply_content = None
134 self.shell._reply_content = None
125
135
126 # Build dict of handlers for message types
136 # Build dict of handlers for message types
127 msg_types = [ 'execute_request', 'complete_request',
137 msg_types = [ 'execute_request', 'complete_request',
128 'object_info_request', 'history_request',
138 'object_info_request', 'history_request',
129 'connect_request', 'shutdown_request']
139 'connect_request', 'shutdown_request']
130 self.handlers = {}
140 self.handlers = {}
131 for msg_type in msg_types:
141 for msg_type in msg_types:
132 self.handlers[msg_type] = getattr(self, msg_type)
142 self.handlers[msg_type] = getattr(self, msg_type)
133
143
134 def do_one_iteration(self):
144 def do_one_iteration(self):
135 """Do one iteration of the kernel's evaluation loop.
145 """Do one iteration of the kernel's evaluation loop.
136 """
146 """
137 try:
147 try:
138 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
148 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
139 except Exception:
149 except Exception:
140 self.log.warn("Invalid Message:", exc_info=True)
150 self.log.warn("Invalid Message:", exc_info=True)
141 return
151 return
142 if msg is None:
152 if msg is None:
143 return
153 return
144
154
145 msg_type = msg['header']['msg_type']
155 msg_type = msg['header']['msg_type']
146
156
147 # This assert will raise in versions of zeromq 2.0.7 and lesser.
157 # This assert will raise in versions of zeromq 2.0.7 and lesser.
148 # We now require 2.0.8 or above, so we can uncomment for safety.
158 # We now require 2.0.8 or above, so we can uncomment for safety.
149 # print(ident,msg, file=sys.__stdout__)
159 # print(ident,msg, file=sys.__stdout__)
150 assert ident is not None, "Missing message part."
160 assert ident is not None, "Missing message part."
151
161
152 # Print some info about this message and leave a '--->' marker, so it's
162 # Print some info about this message and leave a '--->' marker, so it's
153 # easier to trace visually the message chain when debugging. Each
163 # easier to trace visually the message chain when debugging. Each
154 # handler prints its message at the end.
164 # handler prints its message at the end.
155 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
165 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
156 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
166 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
157
167
158 # Find and call actual handler for message
168 # Find and call actual handler for message
159 handler = self.handlers.get(msg_type, None)
169 handler = self.handlers.get(msg_type, None)
160 if handler is None:
170 if handler is None:
161 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
171 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
162 else:
172 else:
163 handler(ident, msg)
173 handler(ident, msg)
164
174
165 # Check whether we should exit, in case the incoming message set the
175 # Check whether we should exit, in case the incoming message set the
166 # exit flag on
176 # exit flag on
167 if self.shell.exit_now:
177 if self.shell.exit_now:
168 self.log.debug('\nExiting IPython kernel...')
178 self.log.debug('\nExiting IPython kernel...')
169 # We do a normal, clean exit, which allows any actions registered
179 # We do a normal, clean exit, which allows any actions registered
170 # via atexit (such as history saving) to take place.
180 # via atexit (such as history saving) to take place.
171 sys.exit(0)
181 sys.exit(0)
172
182
173
183
174 def start(self):
184 def start(self):
175 """ Start the kernel main loop.
185 """ Start the kernel main loop.
176 """
186 """
177 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
187 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
178 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
188 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
179 signal(SIGINT,SIG_IGN)
189 signal(SIGINT,SIG_IGN)
180 poller = zmq.Poller()
190 poller = zmq.Poller()
181 poller.register(self.shell_socket, zmq.POLLIN)
191 poller.register(self.shell_socket, zmq.POLLIN)
182 # loop while self.eventloop has not been overridden
192 # loop while self.eventloop has not been overridden
183 while self.eventloop is None:
193 while self.eventloop is None:
184 try:
194 try:
185 # scale by extra factor of 10, because there is no
195 # scale by extra factor of 10, because there is no
186 # reason for this to be anything less than ~ 0.1s
196 # reason for this to be anything less than ~ 0.1s
187 # since it is a real poller and will respond
197 # since it is a real poller and will respond
188 # to events immediately
198 # to events immediately
189
199
190 # double nested try/except, to properly catch KeyboardInterrupt
200 # double nested try/except, to properly catch KeyboardInterrupt
191 # due to pyzmq Issue #130
201 # due to pyzmq Issue #130
192 try:
202 try:
193 poller.poll(10*1000*self._poll_interval)
203 poller.poll(10*1000*self._poll_interval)
194 # restore raising of KeyboardInterrupt
204 # restore raising of KeyboardInterrupt
195 signal(SIGINT, default_int_handler)
205 signal(SIGINT, default_int_handler)
196 self.do_one_iteration()
206 self.do_one_iteration()
197 except:
207 except:
198 raise
208 raise
199 finally:
209 finally:
200 # prevent raising of KeyboardInterrupt
210 # prevent raising of KeyboardInterrupt
201 signal(SIGINT,SIG_IGN)
211 signal(SIGINT,SIG_IGN)
202 except KeyboardInterrupt:
212 except KeyboardInterrupt:
203 # Ctrl-C shouldn't crash the kernel
213 # Ctrl-C shouldn't crash the kernel
204 io.raw_print("KeyboardInterrupt caught in kernel")
214 io.raw_print("KeyboardInterrupt caught in kernel")
205 # stop ignoring sigint, now that we are out of our own loop,
215 # stop ignoring sigint, now that we are out of our own loop,
206 # we don't want to prevent future code from handling it
216 # we don't want to prevent future code from handling it
207 signal(SIGINT, default_int_handler)
217 signal(SIGINT, default_int_handler)
208 if self.eventloop is not None:
218 if self.eventloop is not None:
209 try:
219 try:
210 self.eventloop(self)
220 self.eventloop(self)
211 except KeyboardInterrupt:
221 except KeyboardInterrupt:
212 # Ctrl-C shouldn't crash the kernel
222 # Ctrl-C shouldn't crash the kernel
213 io.raw_print("KeyboardInterrupt caught in kernel")
223 io.raw_print("KeyboardInterrupt caught in kernel")
214
224
215
225
216 def record_ports(self, ports):
226 def record_ports(self, ports):
217 """Record the ports that this kernel is using.
227 """Record the ports that this kernel is using.
218
228
219 The creator of the Kernel instance must call this methods if they
229 The creator of the Kernel instance must call this methods if they
220 want the :meth:`connect_request` method to return the port numbers.
230 want the :meth:`connect_request` method to return the port numbers.
221 """
231 """
222 self._recorded_ports = ports
232 self._recorded_ports = ports
223
233
224 #---------------------------------------------------------------------------
234 #---------------------------------------------------------------------------
225 # Kernel request handlers
235 # Kernel request handlers
226 #---------------------------------------------------------------------------
236 #---------------------------------------------------------------------------
227
237
228 def _publish_pyin(self, code, parent):
238 def _publish_pyin(self, code, parent):
229 """Publish the code request on the pyin stream."""
239 """Publish the code request on the pyin stream."""
230
240
231 self.session.send(self.iopub_socket, u'pyin', {u'code':code},
241 self.session.send(self.iopub_socket, u'pyin', {u'code':code},
232 parent=parent)
242 parent=parent)
233
243
234 def execute_request(self, ident, parent):
244 def execute_request(self, ident, parent):
235
245
236 self.session.send(self.iopub_socket,
246 self.session.send(self.iopub_socket,
237 u'status',
247 u'status',
238 {u'execution_state':u'busy'},
248 {u'execution_state':u'busy'},
239 parent=parent )
249 parent=parent )
240
250
241 try:
251 try:
242 content = parent[u'content']
252 content = parent[u'content']
243 code = content[u'code']
253 code = content[u'code']
244 silent = content[u'silent']
254 silent = content[u'silent']
245 except:
255 except:
246 self.log.error("Got bad msg: ")
256 self.log.error("Got bad msg: ")
247 self.log.error(str(Message(parent)))
257 self.log.error(str(Message(parent)))
248 return
258 return
249
259
250 shell = self.shell # we'll need this a lot here
260 shell = self.shell # we'll need this a lot here
251
261
252 # Replace raw_input. Note that is not sufficient to replace
262 # Replace raw_input. Note that is not sufficient to replace
253 # raw_input in the user namespace.
263 # raw_input in the user namespace.
254 if content.get('allow_stdin', False):
264 if content.get('allow_stdin', False):
255 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
265 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
256 else:
266 else:
257 raw_input = lambda prompt='' : self._no_raw_input()
267 raw_input = lambda prompt='' : self._no_raw_input()
258
268
259 if py3compat.PY3:
269 if py3compat.PY3:
260 __builtin__.input = raw_input
270 __builtin__.input = raw_input
261 else:
271 else:
262 __builtin__.raw_input = raw_input
272 __builtin__.raw_input = raw_input
263
273
264 # Set the parent message of the display hook and out streams.
274 # Set the parent message of the display hook and out streams.
265 shell.displayhook.set_parent(parent)
275 shell.displayhook.set_parent(parent)
266 shell.display_pub.set_parent(parent)
276 shell.display_pub.set_parent(parent)
267 sys.stdout.set_parent(parent)
277 sys.stdout.set_parent(parent)
268 sys.stderr.set_parent(parent)
278 sys.stderr.set_parent(parent)
269
279
270 # Re-broadcast our input for the benefit of listening clients, and
280 # Re-broadcast our input for the benefit of listening clients, and
271 # start computing output
281 # start computing output
272 if not silent:
282 if not silent:
273 self._publish_pyin(code, parent)
283 self._publish_pyin(code, parent)
274
284
275 reply_content = {}
285 reply_content = {}
276 try:
286 try:
277 if silent:
287 if silent:
278 # run_code uses 'exec' mode, so no displayhook will fire, and it
288 # run_code uses 'exec' mode, so no displayhook will fire, and it
279 # doesn't call logging or history manipulations. Print
289 # doesn't call logging or history manipulations. Print
280 # statements in that code will obviously still execute.
290 # statements in that code will obviously still execute.
281 shell.run_code(code)
291 shell.run_code(code)
282 else:
292 else:
283 # FIXME: the shell calls the exception handler itself.
293 # FIXME: the shell calls the exception handler itself.
284 shell.run_cell(code, store_history=True)
294 shell.run_cell(code, store_history=True)
285 except:
295 except:
286 status = u'error'
296 status = u'error'
287 # FIXME: this code right now isn't being used yet by default,
297 # FIXME: this code right now isn't being used yet by default,
288 # because the run_cell() call above directly fires off exception
298 # because the run_cell() call above directly fires off exception
289 # reporting. This code, therefore, is only active in the scenario
299 # reporting. This code, therefore, is only active in the scenario
290 # where runlines itself has an unhandled exception. We need to
300 # where runlines itself has an unhandled exception. We need to
291 # uniformize this, for all exception construction to come from a
301 # uniformize this, for all exception construction to come from a
292 # single location in the codbase.
302 # single location in the codbase.
293 etype, evalue, tb = sys.exc_info()
303 etype, evalue, tb = sys.exc_info()
294 tb_list = traceback.format_exception(etype, evalue, tb)
304 tb_list = traceback.format_exception(etype, evalue, tb)
295 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
305 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
296 else:
306 else:
297 status = u'ok'
307 status = u'ok'
298
308
299 reply_content[u'status'] = status
309 reply_content[u'status'] = status
300
310
301 # Return the execution counter so clients can display prompts
311 # Return the execution counter so clients can display prompts
302 reply_content['execution_count'] = shell.execution_count -1
312 reply_content['execution_count'] = shell.execution_count -1
303
313
304 # FIXME - fish exception info out of shell, possibly left there by
314 # FIXME - fish exception info out of shell, possibly left there by
305 # runlines. We'll need to clean up this logic later.
315 # runlines. We'll need to clean up this logic later.
306 if shell._reply_content is not None:
316 if shell._reply_content is not None:
307 reply_content.update(shell._reply_content)
317 reply_content.update(shell._reply_content)
308 # reset after use
318 # reset after use
309 shell._reply_content = None
319 shell._reply_content = None
310
320
311 # At this point, we can tell whether the main code execution succeeded
321 # At this point, we can tell whether the main code execution succeeded
312 # or not. If it did, we proceed to evaluate user_variables/expressions
322 # or not. If it did, we proceed to evaluate user_variables/expressions
313 if reply_content['status'] == 'ok':
323 if reply_content['status'] == 'ok':
314 reply_content[u'user_variables'] = \
324 reply_content[u'user_variables'] = \
315 shell.user_variables(content[u'user_variables'])
325 shell.user_variables(content[u'user_variables'])
316 reply_content[u'user_expressions'] = \
326 reply_content[u'user_expressions'] = \
317 shell.user_expressions(content[u'user_expressions'])
327 shell.user_expressions(content[u'user_expressions'])
318 else:
328 else:
319 # If there was an error, don't even try to compute variables or
329 # If there was an error, don't even try to compute variables or
320 # expressions
330 # expressions
321 reply_content[u'user_variables'] = {}
331 reply_content[u'user_variables'] = {}
322 reply_content[u'user_expressions'] = {}
332 reply_content[u'user_expressions'] = {}
323
333
324 # Payloads should be retrieved regardless of outcome, so we can both
334 # Payloads should be retrieved regardless of outcome, so we can both
325 # recover partial output (that could have been generated early in a
335 # recover partial output (that could have been generated early in a
326 # block, before an error) and clear the payload system always.
336 # block, before an error) and clear the payload system always.
327 reply_content[u'payload'] = shell.payload_manager.read_payload()
337 reply_content[u'payload'] = shell.payload_manager.read_payload()
328 # Be agressive about clearing the payload because we don't want
338 # Be agressive about clearing the payload because we don't want
329 # it to sit in memory until the next execute_request comes in.
339 # it to sit in memory until the next execute_request comes in.
330 shell.payload_manager.clear_payload()
340 shell.payload_manager.clear_payload()
331
341
332 # Flush output before sending the reply.
342 # Flush output before sending the reply.
333 sys.stdout.flush()
343 sys.stdout.flush()
334 sys.stderr.flush()
344 sys.stderr.flush()
335 # FIXME: on rare occasions, the flush doesn't seem to make it to the
345 # FIXME: on rare occasions, the flush doesn't seem to make it to the
336 # clients... This seems to mitigate the problem, but we definitely need
346 # clients... This seems to mitigate the problem, but we definitely need
337 # to better understand what's going on.
347 # to better understand what's going on.
338 if self._execute_sleep:
348 if self._execute_sleep:
339 time.sleep(self._execute_sleep)
349 time.sleep(self._execute_sleep)
340
350
341 # Send the reply.
351 # Send the reply.
342 reply_content = json_clean(reply_content)
352 reply_content = json_clean(reply_content)
343 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
353 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
344 reply_content, parent, ident=ident)
354 reply_content, parent, ident=ident)
345 self.log.debug(str(reply_msg))
355 self.log.debug(str(reply_msg))
346
356
347 if reply_msg['content']['status'] == u'error':
357 if reply_msg['content']['status'] == u'error':
348 self._abort_queue()
358 self._abort_queue()
349
359
350 self.session.send(self.iopub_socket,
360 self.session.send(self.iopub_socket,
351 u'status',
361 u'status',
352 {u'execution_state':u'idle'},
362 {u'execution_state':u'idle'},
353 parent=parent )
363 parent=parent )
354
364
355 def complete_request(self, ident, parent):
365 def complete_request(self, ident, parent):
356 txt, matches = self._complete(parent)
366 txt, matches = self._complete(parent)
357 matches = {'matches' : matches,
367 matches = {'matches' : matches,
358 'matched_text' : txt,
368 'matched_text' : txt,
359 'status' : 'ok'}
369 'status' : 'ok'}
360 matches = json_clean(matches)
370 matches = json_clean(matches)
361 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
371 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
362 matches, parent, ident)
372 matches, parent, ident)
363 self.log.debug(str(completion_msg))
373 self.log.debug(str(completion_msg))
364
374
365 def object_info_request(self, ident, parent):
375 def object_info_request(self, ident, parent):
366 object_info = self.shell.object_inspect(parent['content']['oname'])
376 object_info = self.shell.object_inspect(parent['content']['oname'])
367 # Before we send this object over, we scrub it for JSON usage
377 # Before we send this object over, we scrub it for JSON usage
368 oinfo = json_clean(object_info)
378 oinfo = json_clean(object_info)
369 msg = self.session.send(self.shell_socket, 'object_info_reply',
379 msg = self.session.send(self.shell_socket, 'object_info_reply',
370 oinfo, parent, ident)
380 oinfo, parent, ident)
371 self.log.debug(msg)
381 self.log.debug(msg)
372
382
373 def history_request(self, ident, parent):
383 def history_request(self, ident, parent):
374 # We need to pull these out, as passing **kwargs doesn't work with
384 # We need to pull these out, as passing **kwargs doesn't work with
375 # unicode keys before Python 2.6.5.
385 # unicode keys before Python 2.6.5.
376 hist_access_type = parent['content']['hist_access_type']
386 hist_access_type = parent['content']['hist_access_type']
377 raw = parent['content']['raw']
387 raw = parent['content']['raw']
378 output = parent['content']['output']
388 output = parent['content']['output']
379 if hist_access_type == 'tail':
389 if hist_access_type == 'tail':
380 n = parent['content']['n']
390 n = parent['content']['n']
381 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
391 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
382 include_latest=True)
392 include_latest=True)
383
393
384 elif hist_access_type == 'range':
394 elif hist_access_type == 'range':
385 session = parent['content']['session']
395 session = parent['content']['session']
386 start = parent['content']['start']
396 start = parent['content']['start']
387 stop = parent['content']['stop']
397 stop = parent['content']['stop']
388 hist = self.shell.history_manager.get_range(session, start, stop,
398 hist = self.shell.history_manager.get_range(session, start, stop,
389 raw=raw, output=output)
399 raw=raw, output=output)
390
400
391 elif hist_access_type == 'search':
401 elif hist_access_type == 'search':
392 pattern = parent['content']['pattern']
402 pattern = parent['content']['pattern']
393 hist = self.shell.history_manager.search(pattern, raw=raw,
403 hist = self.shell.history_manager.search(pattern, raw=raw,
394 output=output)
404 output=output)
395
405
396 else:
406 else:
397 hist = []
407 hist = []
398 content = {'history' : list(hist)}
408 content = {'history' : list(hist)}
399 content = json_clean(content)
409 content = json_clean(content)
400 msg = self.session.send(self.shell_socket, 'history_reply',
410 msg = self.session.send(self.shell_socket, 'history_reply',
401 content, parent, ident)
411 content, parent, ident)
402 self.log.debug(str(msg))
412 self.log.debug(str(msg))
403
413
404 def connect_request(self, ident, parent):
414 def connect_request(self, ident, parent):
405 if self._recorded_ports is not None:
415 if self._recorded_ports is not None:
406 content = self._recorded_ports.copy()
416 content = self._recorded_ports.copy()
407 else:
417 else:
408 content = {}
418 content = {}
409 msg = self.session.send(self.shell_socket, 'connect_reply',
419 msg = self.session.send(self.shell_socket, 'connect_reply',
410 content, parent, ident)
420 content, parent, ident)
411 self.log.debug(msg)
421 self.log.debug(msg)
412
422
413 def shutdown_request(self, ident, parent):
423 def shutdown_request(self, ident, parent):
414 self.shell.exit_now = True
424 self.shell.exit_now = True
415 self._shutdown_message = self.session.msg(u'shutdown_reply',
425 self._shutdown_message = self.session.msg(u'shutdown_reply',
416 parent['content'], parent)
426 parent['content'], parent)
417 sys.exit(0)
427 sys.exit(0)
418
428
419 #---------------------------------------------------------------------------
429 #---------------------------------------------------------------------------
420 # Protected interface
430 # Protected interface
421 #---------------------------------------------------------------------------
431 #---------------------------------------------------------------------------
422
432
423 def _abort_queue(self):
433 def _abort_queue(self):
424 while True:
434 while True:
425 try:
435 try:
426 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
436 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
427 except Exception:
437 except Exception:
428 self.log.warn("Invalid Message:", exc_info=True)
438 self.log.warn("Invalid Message:", exc_info=True)
429 continue
439 continue
430 if msg is None:
440 if msg is None:
431 break
441 break
432 else:
442 else:
433 assert ident is not None, \
443 assert ident is not None, \
434 "Unexpected missing message part."
444 "Unexpected missing message part."
435
445
436 self.log.debug("Aborting:\n"+str(Message(msg)))
446 self.log.debug("Aborting:\n"+str(Message(msg)))
437 msg_type = msg['header']['msg_type']
447 msg_type = msg['header']['msg_type']
438 reply_type = msg_type.split('_')[0] + '_reply'
448 reply_type = msg_type.split('_')[0] + '_reply'
439 reply_msg = self.session.send(self.shell_socket, reply_type,
449 reply_msg = self.session.send(self.shell_socket, reply_type,
440 {'status' : 'aborted'}, msg, ident=ident)
450 {'status' : 'aborted'}, msg, ident=ident)
441 self.log.debug(reply_msg)
451 self.log.debug(reply_msg)
442 # We need to wait a bit for requests to come in. This can probably
452 # We need to wait a bit for requests to come in. This can probably
443 # be set shorter for true asynchronous clients.
453 # be set shorter for true asynchronous clients.
444 time.sleep(0.1)
454 time.sleep(0.1)
445
455
446 def _no_raw_input(self):
456 def _no_raw_input(self):
447 """Raise StdinNotImplentedError if active frontend doesn't support
457 """Raise StdinNotImplentedError if active frontend doesn't support
448 stdin."""
458 stdin."""
449 raise StdinNotImplementedError("raw_input was called, but this "
459 raise StdinNotImplementedError("raw_input was called, but this "
450 "frontend does not support stdin.")
460 "frontend does not support stdin.")
451
461
452 def _raw_input(self, prompt, ident, parent):
462 def _raw_input(self, prompt, ident, parent):
453 # Flush output before making the request.
463 # Flush output before making the request.
454 sys.stderr.flush()
464 sys.stderr.flush()
455 sys.stdout.flush()
465 sys.stdout.flush()
456
466
457 # Send the input request.
467 # Send the input request.
458 content = json_clean(dict(prompt=prompt))
468 content = json_clean(dict(prompt=prompt))
459 self.session.send(self.stdin_socket, u'input_request', content, parent,
469 self.session.send(self.stdin_socket, u'input_request', content, parent,
460 ident=ident)
470 ident=ident)
461
471
462 # Await a response.
472 # Await a response.
463 while True:
473 while True:
464 try:
474 try:
465 ident, reply = self.session.recv(self.stdin_socket, 0)
475 ident, reply = self.session.recv(self.stdin_socket, 0)
466 except Exception:
476 except Exception:
467 self.log.warn("Invalid Message:", exc_info=True)
477 self.log.warn("Invalid Message:", exc_info=True)
468 else:
478 else:
469 break
479 break
470 try:
480 try:
471 value = reply['content']['value']
481 value = reply['content']['value']
472 except:
482 except:
473 self.log.error("Got bad raw_input reply: ")
483 self.log.error("Got bad raw_input reply: ")
474 self.log.error(str(Message(parent)))
484 self.log.error(str(Message(parent)))
475 value = ''
485 value = ''
476 if value == '\x04':
486 if value == '\x04':
477 # EOF
487 # EOF
478 raise EOFError
488 raise EOFError
479 return value
489 return value
480
490
481 def _complete(self, msg):
491 def _complete(self, msg):
482 c = msg['content']
492 c = msg['content']
483 try:
493 try:
484 cpos = int(c['cursor_pos'])
494 cpos = int(c['cursor_pos'])
485 except:
495 except:
486 # If we don't get something that we can convert to an integer, at
496 # If we don't get something that we can convert to an integer, at
487 # least attempt the completion guessing the cursor is at the end of
497 # least attempt the completion guessing the cursor is at the end of
488 # the text, if there's any, and otherwise of the line
498 # the text, if there's any, and otherwise of the line
489 cpos = len(c['text'])
499 cpos = len(c['text'])
490 if cpos==0:
500 if cpos==0:
491 cpos = len(c['line'])
501 cpos = len(c['line'])
492 return self.shell.complete(c['text'], c['line'], cpos)
502 return self.shell.complete(c['text'], c['line'], cpos)
493
503
494 def _object_info(self, context):
504 def _object_info(self, context):
495 symbol, leftover = self._symbol_from_context(context)
505 symbol, leftover = self._symbol_from_context(context)
496 if symbol is not None and not leftover:
506 if symbol is not None and not leftover:
497 doc = getattr(symbol, '__doc__', '')
507 doc = getattr(symbol, '__doc__', '')
498 else:
508 else:
499 doc = ''
509 doc = ''
500 object_info = dict(docstring = doc)
510 object_info = dict(docstring = doc)
501 return object_info
511 return object_info
502
512
503 def _symbol_from_context(self, context):
513 def _symbol_from_context(self, context):
504 if not context:
514 if not context:
505 return None, context
515 return None, context
506
516
507 base_symbol_string = context[0]
517 base_symbol_string = context[0]
508 symbol = self.shell.user_ns.get(base_symbol_string, None)
518 symbol = self.shell.user_ns.get(base_symbol_string, None)
509 if symbol is None:
519 if symbol is None:
510 symbol = __builtin__.__dict__.get(base_symbol_string, None)
520 symbol = __builtin__.__dict__.get(base_symbol_string, None)
511 if symbol is None:
521 if symbol is None:
512 return None, context
522 return None, context
513
523
514 context = context[1:]
524 context = context[1:]
515 for i, name in enumerate(context):
525 for i, name in enumerate(context):
516 new_symbol = getattr(symbol, name, None)
526 new_symbol = getattr(symbol, name, None)
517 if new_symbol is None:
527 if new_symbol is None:
518 return symbol, context[i:]
528 return symbol, context[i:]
519 else:
529 else:
520 symbol = new_symbol
530 symbol = new_symbol
521
531
522 return symbol, []
532 return symbol, []
523
533
524 def _at_shutdown(self):
534 def _at_shutdown(self):
525 """Actions taken at shutdown by the kernel, called by python's atexit.
535 """Actions taken at shutdown by the kernel, called by python's atexit.
526 """
536 """
527 # io.rprint("Kernel at_shutdown") # dbg
537 # io.rprint("Kernel at_shutdown") # dbg
528 if self._shutdown_message is not None:
538 if self._shutdown_message is not None:
529 self.session.send(self.shell_socket, self._shutdown_message)
539 self.session.send(self.shell_socket, self._shutdown_message)
530 self.session.send(self.iopub_socket, self._shutdown_message)
540 self.session.send(self.iopub_socket, self._shutdown_message)
531 self.log.debug(str(self._shutdown_message))
541 self.log.debug(str(self._shutdown_message))
532 # A very short sleep to give zmq time to flush its message buffers
542 # A very short sleep to give zmq time to flush its message buffers
533 # before Python truly shuts down.
543 # before Python truly shuts down.
534 time.sleep(0.01)
544 time.sleep(0.01)
535
545
536 #-----------------------------------------------------------------------------
546 #-----------------------------------------------------------------------------
537 # Aliases and Flags for the IPKernelApp
547 # Aliases and Flags for the IPKernelApp
538 #-----------------------------------------------------------------------------
548 #-----------------------------------------------------------------------------
539
549
540 flags = dict(kernel_flags)
550 flags = dict(kernel_flags)
541 flags.update(shell_flags)
551 flags.update(shell_flags)
542
552
543 addflag = lambda *args: flags.update(boolean_flag(*args))
553 addflag = lambda *args: flags.update(boolean_flag(*args))
544
554
545 flags['pylab'] = (
555 flags['pylab'] = (
546 {'IPKernelApp' : {'pylab' : 'auto'}},
556 {'IPKernelApp' : {'pylab' : 'auto'}},
547 """Pre-load matplotlib and numpy for interactive use with
557 """Pre-load matplotlib and numpy for interactive use with
548 the default matplotlib backend."""
558 the default matplotlib backend."""
549 )
559 )
550
560
551 aliases = dict(kernel_aliases)
561 aliases = dict(kernel_aliases)
552 aliases.update(shell_aliases)
562 aliases.update(shell_aliases)
553
563
554 # it's possible we don't want short aliases for *all* of these:
564 # it's possible we don't want short aliases for *all* of these:
555 aliases.update(dict(
565 aliases.update(dict(
556 pylab='IPKernelApp.pylab',
566 pylab='IPKernelApp.pylab',
557 ))
567 ))
558
568
559 #-----------------------------------------------------------------------------
569 #-----------------------------------------------------------------------------
560 # The IPKernelApp class
570 # The IPKernelApp class
561 #-----------------------------------------------------------------------------
571 #-----------------------------------------------------------------------------
562
572
563 class IPKernelApp(KernelApp, InteractiveShellApp):
573 class IPKernelApp(KernelApp, InteractiveShellApp):
564 name = 'ipkernel'
574 name = 'ipkernel'
565
575
566 aliases = Dict(aliases)
576 aliases = Dict(aliases)
567 flags = Dict(flags)
577 flags = Dict(flags)
568 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
578 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
579
569 # configurables
580 # configurables
570 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
581 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
571 config=True,
582 config=True,
572 help="""Pre-load matplotlib and numpy for interactive use,
583 help="""Pre-load matplotlib and numpy for interactive use,
573 selecting a particular matplotlib backend and loop integration.
584 selecting a particular matplotlib backend and loop integration.
574 """
585 """
575 )
586 )
576
587
577 @catch_config_error
588 @catch_config_error
578 def initialize(self, argv=None):
589 def initialize(self, argv=None):
579 super(IPKernelApp, self).initialize(argv)
590 super(IPKernelApp, self).initialize(argv)
580 self.init_shell()
591 self.init_shell()
581 self.init_extensions()
592 self.init_extensions()
582 self.init_code()
593 self.init_code()
583
594
584 def init_kernel(self):
595 def init_kernel(self):
585
596
586 kernel = Kernel(config=self.config, session=self.session,
597 kernel = Kernel(config=self.config, session=self.session,
587 shell_socket=self.shell_socket,
598 shell_socket=self.shell_socket,
588 iopub_socket=self.iopub_socket,
599 iopub_socket=self.iopub_socket,
589 stdin_socket=self.stdin_socket,
600 stdin_socket=self.stdin_socket,
590 log=self.log,
601 log=self.log,
591 profile_dir=self.profile_dir,
602 profile_dir=self.profile_dir,
592 user_module=self.user_module,
593 user_ns=self.user_ns,
594 )
603 )
595 self.kernel = kernel
604 self.kernel = kernel
596 kernel.record_ports(self.ports)
605 kernel.record_ports(self.ports)
597 shell = kernel.shell
606 shell = kernel.shell
598 if self.pylab:
607 if self.pylab:
599 try:
608 try:
600 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
609 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
601 shell.enable_pylab(gui, import_all=self.pylab_import_all)
610 shell.enable_pylab(gui, import_all=self.pylab_import_all)
602 except Exception:
611 except Exception:
603 self.log.error("Pylab initialization failed", exc_info=True)
612 self.log.error("Pylab initialization failed", exc_info=True)
604 # print exception straight to stdout, because normally
613 # print exception straight to stdout, because normally
605 # _showtraceback associates the reply with an execution,
614 # _showtraceback associates the reply with an execution,
606 # which means frontends will never draw it, as this exception
615 # which means frontends will never draw it, as this exception
607 # is not associated with any execute request.
616 # is not associated with any execute request.
608
617
609 # replace pyerr-sending traceback with stdout
618 # replace pyerr-sending traceback with stdout
610 _showtraceback = shell._showtraceback
619 _showtraceback = shell._showtraceback
611 def print_tb(etype, evalue, stb):
620 def print_tb(etype, evalue, stb):
612 print ("Error initializing pylab, pylab mode will not "
621 print ("Error initializing pylab, pylab mode will not "
613 "be active", file=io.stderr)
622 "be active", file=io.stderr)
614 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
623 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
615 shell._showtraceback = print_tb
624 shell._showtraceback = print_tb
616
625
617 # send the traceback over stdout
626 # send the traceback over stdout
618 shell.showtraceback(tb_offset=0)
627 shell.showtraceback(tb_offset=0)
619
628
620 # restore proper _showtraceback method
629 # restore proper _showtraceback method
621 shell._showtraceback = _showtraceback
630 shell._showtraceback = _showtraceback
622
631
623
632
624 def init_shell(self):
633 def init_shell(self):
625 self.shell = self.kernel.shell
634 self.shell = self.kernel.shell
626 self.shell.configurables.append(self)
635 self.shell.configurables.append(self)
627
636
628
637
629 #-----------------------------------------------------------------------------
638 #-----------------------------------------------------------------------------
630 # Kernel main and launch functions
639 # Kernel main and launch functions
631 #-----------------------------------------------------------------------------
640 #-----------------------------------------------------------------------------
632
641
633 def launch_kernel(*args, **kwargs):
642 def launch_kernel(*args, **kwargs):
634 """Launches a localhost IPython kernel, binding to the specified ports.
643 """Launches a localhost IPython kernel, binding to the specified ports.
635
644
636 This function simply calls entry_point.base_launch_kernel with the right
645 This function simply calls entry_point.base_launch_kernel with the right
637 first command to start an ipkernel. See base_launch_kernel for arguments.
646 first command to start an ipkernel. See base_launch_kernel for arguments.
638
647
639 Returns
648 Returns
640 -------
649 -------
641 A tuple of form:
650 A tuple of form:
642 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
651 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
643 where kernel_process is a Popen object and the ports are integers.
652 where kernel_process is a Popen object and the ports are integers.
644 """
653 """
645 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
654 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
646 *args, **kwargs)
655 *args, **kwargs)
647
656
648 def embed_kernel(module, local_ns):
657
649 app = IPKernelApp.instance(user_module=module, user_ns=local_ns)
658 def embed_kernel(module=None, local_ns=None, **kwargs):
659 """Embed and start an IPython kernel in a given scope.
660
661 Parameters
662 ----------
663 module : ModuleType, optional
664 The module to load into IPython globals (default: caller)
665 local_ns : dict, optional
666 The namespace to load into IPython user namespace (default: caller)
667
668 kwargs : various, optional
669 Further keyword args are relayed to the KernelApp constructor,
670 allowing configuration of the Kernel. Will only have an effect
671 on the first embed_kernel call for a given process.
672
673 """
674 # get the app if it exists, or set it up if it doesn't
675 if IPKernelApp.initialized():
676 app = IPKernelApp.instance()
677 else:
678 app = IPKernelApp.instance(**kwargs)
650 app.initialize([])
679 app.initialize([])
680
681 # load the calling scope if not given
682 (caller_module, caller_locals) = extract_module_locals(1)
683 if module is None:
684 module = caller_module
685 if local_ns is None:
686 local_ns = caller_locals
687
688 app.kernel.user_module = module
689 app.kernel.user_ns = local_ns
651 app.start()
690 app.start()
652
691
653 def main():
692 def main():
654 """Run an IPKernel as an application"""
693 """Run an IPKernel as an application"""
655 app = IPKernelApp.instance()
694 app = IPKernelApp.instance()
656 app.initialize()
695 app.initialize()
657 app.start()
696 app.start()
658
697
659
698
660 if __name__ == '__main__':
699 if __name__ == '__main__':
661 main()
700 main()
General Comments 0
You need to be logged in to leave comments. Login now