@@ -35,12 +35,13 @@ def validate_string_dict(dct):
35
35
class KernelClient (ConnectionFileMixin ):
36
36
"""Communicates with a single kernel on any host via zmq channels.
37
37
38
- There are four channels associated with each kernel:
38
+ There are five channels associated with each kernel:
39
39
40
40
* shell: for request/reply calls to the kernel.
41
41
* iopub: for the kernel to publish results to frontends.
42
42
* hb: for monitoring the kernel's heartbeat.
43
43
* stdin: for frontends to reply to raw_input calls in the kernel.
44
+ * control: for kernel management calls to the kernel.
44
45
45
46
The messages that can be sent on these channels are exposed as methods of the
46
47
client (KernelClient.execute, complete, history, etc.). These methods only
@@ -58,12 +59,14 @@ def _context_default(self):
58
59
iopub_channel_class = Type (ChannelABC )
59
60
stdin_channel_class = Type (ChannelABC )
60
61
hb_channel_class = Type (HBChannelABC )
62
+ control_channel_class = Type (ChannelABC )
61
63
62
64
# Protected traits
63
65
_shell_channel = Any ()
64
66
_iopub_channel = Any ()
65
67
_stdin_channel = Any ()
66
68
_hb_channel = Any ()
69
+ _control_channel = Any ()
67
70
68
71
# flag for whether execute requests should be allowed to call raw_input:
69
72
allow_stdin = True
@@ -84,11 +87,15 @@ def get_stdin_msg(self, *args, **kwargs):
84
87
"""Get a message from the stdin channel"""
85
88
return self .stdin_channel .get_msg (* args , ** kwargs )
86
89
90
+ def get_control_msg (self , * args , ** kwargs ):
91
+ """Get a message from the control channel"""
92
+ return self .control_channel .get_msg (* args , ** kwargs )
93
+
87
94
#--------------------------------------------------------------------------
88
95
# Channel management methods
89
96
#--------------------------------------------------------------------------
90
97
91
- def start_channels (self , shell = True , iopub = True , stdin = True , hb = True ):
98
+ def start_channels (self , shell = True , iopub = True , stdin = True , hb = True , control = True ):
92
99
"""Starts the channels for this kernel.
93
100
94
101
This will create the channels if they do not exist and then start
@@ -109,6 +116,9 @@ def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):
109
116
self .allow_stdin = False
110
117
if hb :
111
118
self .hb_channel .start ()
119
+ if control :
120
+ self .control_channel .start ()
121
+ self .kernel_info ()
112
122
113
123
def stop_channels (self ):
114
124
"""Stops all the running channels for this kernel.
@@ -123,12 +133,15 @@ def stop_channels(self):
123
133
self .stdin_channel .stop ()
124
134
if self .hb_channel .is_alive ():
125
135
self .hb_channel .stop ()
136
+ if self .control_channel .is_alive ():
137
+ self .control_channel .stop ()
126
138
127
139
@property
128
140
def channels_running (self ):
129
141
"""Are any of the channels created and running?"""
130
142
return (self .shell_channel .is_alive () or self .iopub_channel .is_alive () or
131
- self .stdin_channel .is_alive () or self .hb_channel .is_alive ())
143
+ self .stdin_channel .is_alive () or self .hb_channel .is_alive () or
144
+ self .control_channel .is_alive ())
132
145
133
146
ioloop = None # Overridden in subclasses that use pyzmq event loop
134
147
@@ -179,6 +192,18 @@ def hb_channel(self):
179
192
)
180
193
return self ._hb_channel
181
194
195
+ @property
196
+ def control_channel (self ):
197
+ """Get the control channel object for this kernel."""
198
+ if self ._control_channel is None :
199
+ url = self ._make_url ('control' )
200
+ self .log .debug ("connecting control channel to %s" , url )
201
+ socket = self .connect_control (identity = self .session .bsession )
202
+ self ._control_channel = self .control_channel_class (
203
+ socket , self .session , self .ioloop
204
+ )
205
+ return self ._control_channel
206
+
182
207
def is_alive (self ):
183
208
"""Is the kernel process still running?"""
184
209
from .manager import KernelManager
@@ -401,7 +426,7 @@ def shutdown(self, restart=False):
401
426
# Send quit message to kernel. Once we implement kernel-side setattr,
402
427
# this should probably be done that way, but for now this will do.
403
428
msg = self .session .msg ('shutdown_request' , {'restart' :restart })
404
- self .shell_channel .send (msg )
429
+ self .control_channel .send (msg )
405
430
return msg ['header' ]['msg_id' ]
406
431
407
432
def is_complete (self , code ):
0 commit comments