@@ -52,18 +52,17 @@ class MultiKernelManager(LoggingConfigurable):
52
52
"""A class for managing multiple kernels."""
53
53
54
54
default_kernel_name = Unicode (
55
- NATIVE_KERNEL_NAME , config = True , help = "The name of the default kernel to start"
56
- )
55
+ NATIVE_KERNEL_NAME , help = "The name of the default kernel to start"
56
+ ). tag ( config = True )
57
57
58
58
kernel_spec_manager = Instance (KernelSpecManager , allow_none = True )
59
59
60
60
kernel_manager_class = DottedObjectName (
61
61
"jupyter_client.ioloop.IOLoopKernelManager" ,
62
- config = True ,
63
62
help = """The kernel manager class. This is configurable to allow
64
63
subclassing of the KernelManager for customized behavior.
65
64
""" ,
66
- )
65
+ ). tag ( config = True )
67
66
68
67
@observe ("kernel_manager_class" )
69
68
def _kernel_manager_class_changed (self , change ):
@@ -91,9 +90,8 @@ def create_kernel_manager(*args, **kwargs) -> KernelManager:
91
90
92
91
shared_context = Bool (
93
92
True ,
94
- config = True ,
95
93
help = "Share a single zmq.Context to talk to all my kernels" ,
96
- )
94
+ ). tag ( config = True )
97
95
98
96
_created_context = Bool (False )
99
97
@@ -163,8 +161,11 @@ def pre_start_kernel(
163
161
async def _add_kernel_when_ready (
164
162
self , kernel_id : str , km : KernelManager , kernel_awaitable : t .Awaitable
165
163
) -> None :
166
- await kernel_awaitable
167
- self ._kernels [kernel_id ] = km
164
+ try :
165
+ await kernel_awaitable
166
+ self ._kernels [kernel_id ] = km
167
+ finally :
168
+ self ._starting_kernels .pop (kernel_id , None )
168
169
169
170
async def _async_start_kernel (self , kernel_name : t .Optional [str ] = None , ** kwargs ) -> str :
170
171
"""Start a new kernel.
@@ -182,12 +183,16 @@ async def _async_start_kernel(self, kernel_name: t.Optional[str] = None, **kwarg
182
183
)
183
184
)
184
185
kwargs ['kernel_id' ] = kernel_id # Make kernel_id available to manager and provisioner
185
- fut = asyncio . ensure_future (
186
- self . _add_kernel_when_ready ( kernel_id , km , ensure_async (km .start_kernel (** kwargs ) ))
187
- )
186
+
187
+ starter = ensure_async (km .start_kernel (** kwargs ))
188
+ fut = asyncio . ensure_future ( self . _add_kernel_when_ready ( kernel_id , km , starter ) )
188
189
self ._starting_kernels [kernel_id ] = fut
189
- await fut
190
- del self ._starting_kernels [kernel_id ]
190
+
191
+ if getattr (self , 'use_pending_kernels' , False ):
192
+ self ._kernels [kernel_id ] = km
193
+ else :
194
+ await fut
195
+
191
196
return kernel_id
192
197
193
198
start_kernel = run_sync (_async_start_kernel )
@@ -210,9 +215,13 @@ async def _async_shutdown_kernel(
210
215
Will the kernel be restarted?
211
216
"""
212
217
self .log .info ("Kernel shutdown: %s" % kernel_id )
213
-
218
+ if kernel_id in self ._starting_kernels :
219
+ try :
220
+ await self ._starting_kernels [kernel_id ]
221
+ except Exception :
222
+ self .remove_kernel (kernel_id )
223
+ return
214
224
km = self .get_kernel (kernel_id )
215
-
216
225
await ensure_async (km .shutdown_kernel (now , restart ))
217
226
self .remove_kernel (kernel_id )
218
227
@@ -246,18 +255,11 @@ def remove_kernel(self, kernel_id: str) -> KernelManager:
246
255
"""
247
256
return self ._kernels .pop (kernel_id , None )
248
257
249
- async def _shutdown_starting_kernel (self , kid : str , now : bool ) -> None :
250
- if kid in self ._starting_kernels :
251
- await self ._starting_kernels [kid ]
252
- await ensure_async (self .shutdown_kernel (kid , now = now ))
253
-
254
258
async def _async_shutdown_all (self , now : bool = False ) -> None :
255
259
"""Shutdown all kernels."""
256
260
kids = self .list_kernel_ids ()
257
- futs = [ensure_async (self .shutdown_kernel (kid , now = now )) for kid in kids ]
258
- futs += [
259
- self ._shutdown_starting_kernel (kid , now = now ) for kid in self ._starting_kernels .keys ()
260
- ]
261
+ kids += list (self ._starting_kernels )
262
+ futs = [ensure_async (self .shutdown_kernel (kid , now = now )) for kid in set (kids )]
261
263
await asyncio .gather (* futs )
262
264
263
265
shutdown_all = run_sync (_async_shutdown_all )
@@ -466,6 +468,12 @@ class AsyncMultiKernelManager(MultiKernelManager):
466
468
""" ,
467
469
)
468
470
471
+ use_pending_kernels = Bool (
472
+ False ,
473
+ help = """Whether to make kernels available before the process has started. The
474
+ kernel has a `.ready` future which can be awaited before connecting""" ,
475
+ ).tag (config = True )
476
+
469
477
start_kernel = MultiKernelManager ._async_start_kernel
470
478
shutdown_kernel = MultiKernelManager ._async_shutdown_kernel
471
479
shutdown_all = MultiKernelManager ._async_shutdown_all
0 commit comments