##// END OF EJS Templates
add missing `now` to MKM.restart
MinRK -
Show More
@@ -1,301 +1,301 b''
1 """A kernel manager for multiple kernels
1 """A kernel manager for multiple kernels
2
2
3 Authors:
3 Authors:
4
4
5 * Brian Granger
5 * Brian Granger
6 """
6 """
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2013 The IPython Development Team
9 # Copyright (C) 2013 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from __future__ import absolute_import
19 from __future__ import absolute_import
20
20
21 import os
21 import os
22 import uuid
22 import uuid
23
23
24 import zmq
24 import zmq
25
25
26 from IPython.config.configurable import LoggingConfigurable
26 from IPython.config.configurable import LoggingConfigurable
27 from IPython.utils.importstring import import_item
27 from IPython.utils.importstring import import_item
28 from IPython.utils.traitlets import (
28 from IPython.utils.traitlets import (
29 Instance, Dict, Unicode, Any, DottedObjectName
29 Instance, Dict, Unicode, Any, DottedObjectName
30 )
30 )
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Classes
33 # Classes
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 class DuplicateKernelError(Exception):
36 class DuplicateKernelError(Exception):
37 pass
37 pass
38
38
39
39
40
40
41 def kernel_method(f):
41 def kernel_method(f):
42 """decorator for proxying MKM.method(kernel_id) to individual KMs by ID"""
42 """decorator for proxying MKM.method(kernel_id) to individual KMs by ID"""
43 def wrapped(self, kernel_id, *args, **kwargs):
43 def wrapped(self, kernel_id, *args, **kwargs):
44 # get the kernel
44 # get the kernel
45 km = self.get_kernel(kernel_id)
45 km = self.get_kernel(kernel_id)
46 method = getattr(km, f.__name__)
46 method = getattr(km, f.__name__)
47 # call the kernel's method
47 # call the kernel's method
48 r = method(*args, **kwargs)
48 r = method(*args, **kwargs)
49 # last thing, call anything defined in the actual class method
49 # last thing, call anything defined in the actual class method
50 # such as logging messages
50 # such as logging messages
51 f(self, kernel_id, *args, **kwargs)
51 f(self, kernel_id, *args, **kwargs)
52 # return the method result
52 # return the method result
53 return r
53 return r
54 return wrapped
54 return wrapped
55
55
56
56
57 class MultiKernelManager(LoggingConfigurable):
57 class MultiKernelManager(LoggingConfigurable):
58 """A class for managing multiple kernels."""
58 """A class for managing multiple kernels."""
59
59
60 kernel_manager_class = DottedObjectName(
60 kernel_manager_class = DottedObjectName(
61 "IPython.kernel.ioloop.IOLoopKernelManager", config=True,
61 "IPython.kernel.ioloop.IOLoopKernelManager", config=True,
62 help="""The kernel manager class. This is configurable to allow
62 help="""The kernel manager class. This is configurable to allow
63 subclassing of the KernelManager for customized behavior.
63 subclassing of the KernelManager for customized behavior.
64 """
64 """
65 )
65 )
66 def _kernel_manager_class_changed(self, name, old, new):
66 def _kernel_manager_class_changed(self, name, old, new):
67 self.kernel_manager_factory = import_item(new)
67 self.kernel_manager_factory = import_item(new)
68
68
69 kernel_manager_factory = Any(help="this is kernel_manager_class after import")
69 kernel_manager_factory = Any(help="this is kernel_manager_class after import")
70 def _kernel_manager_factory_default(self):
70 def _kernel_manager_factory_default(self):
71 return import_item(self.kernel_manager_class)
71 return import_item(self.kernel_manager_class)
72
72
73 context = Instance('zmq.Context')
73 context = Instance('zmq.Context')
74 def _context_default(self):
74 def _context_default(self):
75 return zmq.Context.instance()
75 return zmq.Context.instance()
76
76
77 connection_dir = Unicode('')
77 connection_dir = Unicode('')
78
78
79 _kernels = Dict()
79 _kernels = Dict()
80
80
81 def list_kernel_ids(self):
81 def list_kernel_ids(self):
82 """Return a list of the kernel ids of the active kernels."""
82 """Return a list of the kernel ids of the active kernels."""
83 # Create a copy so we can iterate over kernels in operations
83 # Create a copy so we can iterate over kernels in operations
84 # that delete keys.
84 # that delete keys.
85 return list(self._kernels.keys())
85 return list(self._kernels.keys())
86
86
87 def __len__(self):
87 def __len__(self):
88 """Return the number of running kernels."""
88 """Return the number of running kernels."""
89 return len(self.list_kernel_ids())
89 return len(self.list_kernel_ids())
90
90
91 def __contains__(self, kernel_id):
91 def __contains__(self, kernel_id):
92 return kernel_id in self._kernels
92 return kernel_id in self._kernels
93
93
94 def start_kernel(self, **kwargs):
94 def start_kernel(self, **kwargs):
95 """Start a new kernel.
95 """Start a new kernel.
96
96
97 The caller can pick a kernel_id by passing one in as a keyword arg,
97 The caller can pick a kernel_id by passing one in as a keyword arg,
98 otherwise one will be picked using a uuid.
98 otherwise one will be picked using a uuid.
99
99
100 To silence the kernel's stdout/stderr, call this using::
100 To silence the kernel's stdout/stderr, call this using::
101
101
102 km.start_kernel(stdout=PIPE, stderr=PIPE)
102 km.start_kernel(stdout=PIPE, stderr=PIPE)
103
103
104 """
104 """
105 kernel_id = kwargs.pop('kernel_id', unicode(uuid.uuid4()))
105 kernel_id = kwargs.pop('kernel_id', unicode(uuid.uuid4()))
106 if kernel_id in self:
106 if kernel_id in self:
107 raise DuplicateKernelError('Kernel already exists: %s' % kernel_id)
107 raise DuplicateKernelError('Kernel already exists: %s' % kernel_id)
108 # kernel_manager_factory is the constructor for the KernelManager
108 # kernel_manager_factory is the constructor for the KernelManager
109 # subclass we are using. It can be configured as any Configurable,
109 # subclass we are using. It can be configured as any Configurable,
110 # including things like its transport and ip.
110 # including things like its transport and ip.
111 km = self.kernel_manager_factory(connection_file=os.path.join(
111 km = self.kernel_manager_factory(connection_file=os.path.join(
112 self.connection_dir, "kernel-%s.json" % kernel_id),
112 self.connection_dir, "kernel-%s.json" % kernel_id),
113 parent=self, autorestart=True, log=self.log
113 parent=self, autorestart=True, log=self.log
114 )
114 )
115 km.start_kernel(**kwargs)
115 km.start_kernel(**kwargs)
116 self._kernels[kernel_id] = km
116 self._kernels[kernel_id] = km
117 return kernel_id
117 return kernel_id
118
118
119 @kernel_method
119 @kernel_method
120 def shutdown_kernel(self, kernel_id, now=False):
120 def shutdown_kernel(self, kernel_id, now=False):
121 """Shutdown a kernel by its kernel uuid.
121 """Shutdown a kernel by its kernel uuid.
122
122
123 Parameters
123 Parameters
124 ==========
124 ==========
125 kernel_id : uuid
125 kernel_id : uuid
126 The id of the kernel to shutdown.
126 The id of the kernel to shutdown.
127 now : bool
127 now : bool
128 Should the kernel be shutdown forcibly using a signal.
128 Should the kernel be shutdown forcibly using a signal.
129 """
129 """
130 self.log.info("Kernel shutdown: %s" % kernel_id)
130 self.log.info("Kernel shutdown: %s" % kernel_id)
131 self.remove_kernel(kernel_id)
131 self.remove_kernel(kernel_id)
132
132
133 def remove_kernel(self, kernel_id):
133 def remove_kernel(self, kernel_id):
134 """remove a kernel from our mapping.
134 """remove a kernel from our mapping.
135
135
136 Mainly so that a kernel can be removed if it is already dead,
136 Mainly so that a kernel can be removed if it is already dead,
137 without having to call shutdown_kernel.
137 without having to call shutdown_kernel.
138
138
139 The kernel object is returned.
139 The kernel object is returned.
140 """
140 """
141 return self._kernels.pop(kernel_id)
141 return self._kernels.pop(kernel_id)
142
142
143 def shutdown_all(self, now=False):
143 def shutdown_all(self, now=False):
144 """Shutdown all kernels."""
144 """Shutdown all kernels."""
145 for kid in self.list_kernel_ids():
145 for kid in self.list_kernel_ids():
146 self.shutdown_kernel(kid, now=now)
146 self.shutdown_kernel(kid, now=now)
147
147
148 @kernel_method
148 @kernel_method
149 def interrupt_kernel(self, kernel_id):
149 def interrupt_kernel(self, kernel_id):
150 """Interrupt (SIGINT) the kernel by its uuid.
150 """Interrupt (SIGINT) the kernel by its uuid.
151
151
152 Parameters
152 Parameters
153 ==========
153 ==========
154 kernel_id : uuid
154 kernel_id : uuid
155 The id of the kernel to interrupt.
155 The id of the kernel to interrupt.
156 """
156 """
157 self.log.info("Kernel interrupted: %s" % kernel_id)
157 self.log.info("Kernel interrupted: %s" % kernel_id)
158
158
159 @kernel_method
159 @kernel_method
160 def signal_kernel(self, kernel_id, signum):
160 def signal_kernel(self, kernel_id, signum):
161 """Sends a signal to the kernel by its uuid.
161 """Sends a signal to the kernel by its uuid.
162
162
163 Note that since only SIGTERM is supported on Windows, this function
163 Note that since only SIGTERM is supported on Windows, this function
164 is only useful on Unix systems.
164 is only useful on Unix systems.
165
165
166 Parameters
166 Parameters
167 ==========
167 ==========
168 kernel_id : uuid
168 kernel_id : uuid
169 The id of the kernel to signal.
169 The id of the kernel to signal.
170 """
170 """
171 self.log.info("Signaled Kernel %s with %s" % (kernel_id, signum))
171 self.log.info("Signaled Kernel %s with %s" % (kernel_id, signum))
172
172
173 @kernel_method
173 @kernel_method
174 def restart_kernel(self, kernel_id):
174 def restart_kernel(self, kernel_id, now=False):
175 """Restart a kernel by its uuid, keeping the same ports.
175 """Restart a kernel by its uuid, keeping the same ports.
176
176
177 Parameters
177 Parameters
178 ==========
178 ==========
179 kernel_id : uuid
179 kernel_id : uuid
180 The id of the kernel to interrupt.
180 The id of the kernel to interrupt.
181 """
181 """
182 self.log.info("Kernel restarted: %s" % kernel_id)
182 self.log.info("Kernel restarted: %s" % kernel_id)
183
183
184 @kernel_method
184 @kernel_method
185 def is_alive(self, kernel_id):
185 def is_alive(self, kernel_id):
186 """Is the kernel alive.
186 """Is the kernel alive.
187
187
188 This calls KernelManager.is_alive() which calls Popen.poll on the
188 This calls KernelManager.is_alive() which calls Popen.poll on the
189 actual kernel subprocess.
189 actual kernel subprocess.
190
190
191 Parameters
191 Parameters
192 ==========
192 ==========
193 kernel_id : uuid
193 kernel_id : uuid
194 The id of the kernel.
194 The id of the kernel.
195 """
195 """
196
196
197 def _check_kernel_id(self, kernel_id):
197 def _check_kernel_id(self, kernel_id):
198 """check that a kernel id is valid"""
198 """check that a kernel id is valid"""
199 if kernel_id not in self:
199 if kernel_id not in self:
200 raise KeyError("Kernel with id not found: %s" % kernel_id)
200 raise KeyError("Kernel with id not found: %s" % kernel_id)
201
201
202 def get_kernel(self, kernel_id):
202 def get_kernel(self, kernel_id):
203 """Get the single KernelManager object for a kernel by its uuid.
203 """Get the single KernelManager object for a kernel by its uuid.
204
204
205 Parameters
205 Parameters
206 ==========
206 ==========
207 kernel_id : uuid
207 kernel_id : uuid
208 The id of the kernel.
208 The id of the kernel.
209 """
209 """
210 self._check_kernel_id(kernel_id)
210 self._check_kernel_id(kernel_id)
211 return self._kernels[kernel_id]
211 return self._kernels[kernel_id]
212
212
213 @kernel_method
213 @kernel_method
214 def add_restart_callback(self, kernel_id, callback, event='restart'):
214 def add_restart_callback(self, kernel_id, callback, event='restart'):
215 """add a callback for the KernelRestarter"""
215 """add a callback for the KernelRestarter"""
216
216
217 @kernel_method
217 @kernel_method
218 def remove_restart_callback(self, kernel_id, callback, event='restart'):
218 def remove_restart_callback(self, kernel_id, callback, event='restart'):
219 """remove a callback for the KernelRestarter"""
219 """remove a callback for the KernelRestarter"""
220
220
221 @kernel_method
221 @kernel_method
222 def get_connection_info(self, kernel_id):
222 def get_connection_info(self, kernel_id):
223 """Return a dictionary of connection data for a kernel.
223 """Return a dictionary of connection data for a kernel.
224
224
225 Parameters
225 Parameters
226 ==========
226 ==========
227 kernel_id : uuid
227 kernel_id : uuid
228 The id of the kernel.
228 The id of the kernel.
229
229
230 Returns
230 Returns
231 =======
231 =======
232 connection_dict : dict
232 connection_dict : dict
233 A dict of the information needed to connect to a kernel.
233 A dict of the information needed to connect to a kernel.
234 This includes the ip address and the integer port
234 This includes the ip address and the integer port
235 numbers of the different channels (stdin_port, iopub_port,
235 numbers of the different channels (stdin_port, iopub_port,
236 shell_port, hb_port).
236 shell_port, hb_port).
237 """
237 """
238
238
239 @kernel_method
239 @kernel_method
240 def connect_iopub(self, kernel_id, identity=None):
240 def connect_iopub(self, kernel_id, identity=None):
241 """Return a zmq Socket connected to the iopub channel.
241 """Return a zmq Socket connected to the iopub channel.
242
242
243 Parameters
243 Parameters
244 ==========
244 ==========
245 kernel_id : uuid
245 kernel_id : uuid
246 The id of the kernel
246 The id of the kernel
247 identity : bytes (optional)
247 identity : bytes (optional)
248 The zmq identity of the socket
248 The zmq identity of the socket
249
249
250 Returns
250 Returns
251 =======
251 =======
252 stream : zmq Socket or ZMQStream
252 stream : zmq Socket or ZMQStream
253 """
253 """
254
254
255 @kernel_method
255 @kernel_method
256 def connect_shell(self, kernel_id, identity=None):
256 def connect_shell(self, kernel_id, identity=None):
257 """Return a zmq Socket connected to the shell channel.
257 """Return a zmq Socket connected to the shell channel.
258
258
259 Parameters
259 Parameters
260 ==========
260 ==========
261 kernel_id : uuid
261 kernel_id : uuid
262 The id of the kernel
262 The id of the kernel
263 identity : bytes (optional)
263 identity : bytes (optional)
264 The zmq identity of the socket
264 The zmq identity of the socket
265
265
266 Returns
266 Returns
267 =======
267 =======
268 stream : zmq Socket or ZMQStream
268 stream : zmq Socket or ZMQStream
269 """
269 """
270
270
271 @kernel_method
271 @kernel_method
272 def connect_stdin(self, kernel_id, identity=None):
272 def connect_stdin(self, kernel_id, identity=None):
273 """Return a zmq Socket connected to the stdin channel.
273 """Return a zmq Socket connected to the stdin channel.
274
274
275 Parameters
275 Parameters
276 ==========
276 ==========
277 kernel_id : uuid
277 kernel_id : uuid
278 The id of the kernel
278 The id of the kernel
279 identity : bytes (optional)
279 identity : bytes (optional)
280 The zmq identity of the socket
280 The zmq identity of the socket
281
281
282 Returns
282 Returns
283 =======
283 =======
284 stream : zmq Socket or ZMQStream
284 stream : zmq Socket or ZMQStream
285 """
285 """
286
286
287 @kernel_method
287 @kernel_method
288 def connect_hb(self, kernel_id, identity=None):
288 def connect_hb(self, kernel_id, identity=None):
289 """Return a zmq Socket connected to the hb channel.
289 """Return a zmq Socket connected to the hb channel.
290
290
291 Parameters
291 Parameters
292 ==========
292 ==========
293 kernel_id : uuid
293 kernel_id : uuid
294 The id of the kernel
294 The id of the kernel
295 identity : bytes (optional)
295 identity : bytes (optional)
296 The zmq identity of the socket
296 The zmq identity of the socket
297
297
298 Returns
298 Returns
299 =======
299 =======
300 stream : zmq Socket or ZMQStream
300 stream : zmq Socket or ZMQStream
301 """
301 """
General Comments 0
You need to be logged in to leave comments. Login now