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