##// END OF EJS Templates
make sure connection info gets printed when starting a kernel...
MinRK -
Show More
@@ -1,226 +1,227 b''
1 1 #!/usr/bin/env python
2 2 """An Application for launching a kernel
3 3
4 4 Authors
5 5 -------
6 6 * MinRK
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2011 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING.txt, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # Standard library imports.
20 20 import os
21 21 import sys
22 22
23 23 # System library imports.
24 24 import zmq
25 25
26 26 # IPython imports.
27 27 from IPython.core.ultratb import FormattedTB
28 28 from IPython.core.application import (
29 29 BaseIPythonApplication, base_flags, base_aliases
30 30 )
31 31 from IPython.utils import io
32 32 from IPython.utils.localinterfaces import LOCALHOST
33 33 from IPython.utils.traitlets import (Any, Instance, Dict, Unicode, Int, Bool,
34 34 DottedObjectName)
35 35 from IPython.utils.importstring import import_item
36 36 # local imports
37 37 from IPython.zmq.heartbeat import Heartbeat
38 38 from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
39 39 from IPython.zmq.session import Session
40 40
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Flags and Aliases
44 44 #-----------------------------------------------------------------------------
45 45
46 46 kernel_aliases = dict(base_aliases)
47 47 kernel_aliases.update({
48 48 'ip' : 'KernelApp.ip',
49 49 'hb' : 'KernelApp.hb_port',
50 50 'shell' : 'KernelApp.shell_port',
51 51 'iopub' : 'KernelApp.iopub_port',
52 52 'stdin' : 'KernelApp.stdin_port',
53 53 'parent': 'KernelApp.parent',
54 54 })
55 55 if sys.platform.startswith('win'):
56 56 kernel_aliases['interrupt'] = 'KernelApp.interrupt'
57 57
58 58 kernel_flags = dict(base_flags)
59 59 kernel_flags.update({
60 60 'no-stdout' : (
61 61 {'KernelApp' : {'no_stdout' : True}},
62 62 "redirect stdout to the null device"),
63 63 'no-stderr' : (
64 64 {'KernelApp' : {'no_stderr' : True}},
65 65 "redirect stderr to the null device"),
66 66 })
67 67
68 68
69 69 #-----------------------------------------------------------------------------
70 70 # Application class for starting a Kernel
71 71 #-----------------------------------------------------------------------------
72 72
73 73 class KernelApp(BaseIPythonApplication):
74 74 name='pykernel'
75 75 aliases = Dict(kernel_aliases)
76 76 flags = Dict(kernel_flags)
77 77 classes = [Session]
78 78 # the kernel class, as an importstring
79 79 kernel_class = DottedObjectName('IPython.zmq.pykernel.Kernel')
80 80 kernel = Any()
81 81 poller = Any() # don't restrict this even though current pollers are all Threads
82 82 heartbeat = Instance(Heartbeat)
83 83 session = Instance('IPython.zmq.session.Session')
84 84 ports = Dict()
85 85
86 86 # inherit config file name from parent:
87 87 parent_appname = Unicode(config=True)
88 88 def _parent_appname_changed(self, name, old, new):
89 89 if self.config_file_specified:
90 90 # it was manually specified, ignore
91 91 return
92 92 self.config_file_name = new.replace('-','_') + u'_config.py'
93 93 # don't let this count as specifying the config file
94 94 self.config_file_specified = False
95 95
96 96 # connection info:
97 97 ip = Unicode(LOCALHOST, config=True,
98 98 help="Set the IP or interface on which the kernel will listen.")
99 99 hb_port = Int(0, config=True, help="set the heartbeat port [default: random]")
100 100 shell_port = Int(0, config=True, help="set the shell (XREP) port [default: random]")
101 101 iopub_port = Int(0, config=True, help="set the iopub (PUB) port [default: random]")
102 102 stdin_port = Int(0, config=True, help="set the stdin (XREQ) port [default: random]")
103 103
104 104 # streams, etc.
105 105 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
106 106 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
107 107 outstream_class = DottedObjectName('IPython.zmq.iostream.OutStream',
108 108 config=True, help="The importstring for the OutStream factory")
109 109 displayhook_class = DottedObjectName('IPython.zmq.displayhook.ZMQDisplayHook',
110 110 config=True, help="The importstring for the DisplayHook factory")
111 111
112 112 # polling
113 113 parent = Int(0, config=True,
114 114 help="""kill this process if its parent dies. On Windows, the argument
115 115 specifies the HANDLE of the parent process, otherwise it is simply boolean.
116 116 """)
117 117 interrupt = Int(0, config=True,
118 118 help="""ONLY USED ON WINDOWS
119 119 Interrupt this process when the parent is signalled.
120 120 """)
121 121
122 122 def init_crash_handler(self):
123 123 # Install minimal exception handling
124 124 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
125 125 ostream=sys.__stdout__)
126 126
127 127 def init_poller(self):
128 128 if sys.platform == 'win32':
129 129 if self.interrupt or self.parent:
130 130 self.poller = ParentPollerWindows(self.interrupt, self.parent)
131 131 elif self.parent:
132 132 self.poller = ParentPollerUnix()
133 133
134 134 def _bind_socket(self, s, port):
135 135 iface = 'tcp://%s' % self.ip
136 136 if port <= 0:
137 137 port = s.bind_to_random_port(iface)
138 138 else:
139 139 s.bind(iface + ':%i'%port)
140 140 return port
141 141
142 142 def init_sockets(self):
143 143 # Create a context, a session, and the kernel sockets.
144 io.raw_print("Starting the kernel at pid:", os.getpid())
144 self.log.info("Starting the kernel at pid:", os.getpid())
145 145 context = zmq.Context.instance()
146 146 # Uncomment this to try closing the context.
147 147 # atexit.register(context.term)
148 148
149 149 self.shell_socket = context.socket(zmq.XREP)
150 150 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
151 151 self.log.debug("shell XREP Channel on port: %i"%self.shell_port)
152 152
153 153 self.iopub_socket = context.socket(zmq.PUB)
154 154 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
155 155 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
156 156
157 157 self.stdin_socket = context.socket(zmq.XREQ)
158 158 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
159 159 self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
160 160
161 161 self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
162 162 self.hb_port = self.heartbeat.port
163 163 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
164 164
165 165 # Helper to make it easier to connect to an existing kernel, until we have
166 166 # single-port connection negotiation fully implemented.
167 self.log.info("To connect another client to this kernel, use:")
168 self.log.info("--external shell={0} iopub={1} stdin={2} hb={3}".format(
167 # set log-level to critical, to make sure it is output
168 self.log.critical("To connect another client to this kernel, use:")
169 self.log.critical("--existing shell={0} iopub={1} stdin={2} hb={3}".format(
169 170 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port))
170 171
171 172
172 173 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
173 174 stdin=self.stdin_port, hb=self.hb_port)
174 175
175 176 def init_session(self):
176 177 """create our session object"""
177 178 self.session = Session(config=self.config, username=u'kernel')
178 179
179 180 def init_blackhole(self):
180 181 """redirects stdout/stderr to devnull if necessary"""
181 182 if self.no_stdout or self.no_stderr:
182 183 blackhole = file(os.devnull, 'w')
183 184 if self.no_stdout:
184 185 sys.stdout = sys.__stdout__ = blackhole
185 186 if self.no_stderr:
186 187 sys.stderr = sys.__stderr__ = blackhole
187 188
188 189 def init_io(self):
189 190 """Redirect input streams and set a display hook."""
190 191 if self.outstream_class:
191 192 outstream_factory = import_item(str(self.outstream_class))
192 193 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
193 194 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
194 195 if self.displayhook_class:
195 196 displayhook_factory = import_item(str(self.displayhook_class))
196 197 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
197 198
198 199 def init_kernel(self):
199 200 """Create the Kernel object itself"""
200 201 kernel_factory = import_item(str(self.kernel_class))
201 202 self.kernel = kernel_factory(config=self.config, session=self.session,
202 203 shell_socket=self.shell_socket,
203 204 iopub_socket=self.iopub_socket,
204 205 stdin_socket=self.stdin_socket,
205 206 log=self.log
206 207 )
207 208 self.kernel.record_ports(self.ports)
208 209
209 210 def initialize(self, argv=None):
210 211 super(KernelApp, self).initialize(argv)
211 212 self.init_blackhole()
212 213 self.init_session()
213 214 self.init_poller()
214 215 self.init_sockets()
215 216 self.init_io()
216 217 self.init_kernel()
217 218
218 219 def start(self):
219 220 self.heartbeat.start()
220 221 if self.poller is not None:
221 222 self.poller.start()
222 223 try:
223 224 self.kernel.start()
224 225 except KeyboardInterrupt:
225 226 pass
226 227
General Comments 0
You need to be logged in to leave comments. Login now