##// END OF EJS Templates
don't limit ports to 1024
MinRK -
Show More
@@ -1,371 +1,372 b''
1 """An Application for launching a kernel
1 """An Application for launching a kernel
2
2
3 Authors
3 Authors
4 -------
4 -------
5 * MinRK
5 * MinRK
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2011 The IPython Development Team
8 # Copyright (C) 2011 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING.txt, distributed as part of this software.
11 # the file COPYING.txt, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Standard library imports
18 # Standard library imports
19 import atexit
19 import atexit
20 import json
20 import json
21 import os
21 import os
22 import sys
22 import sys
23 import signal
23 import signal
24
24
25 # System library imports
25 # System library imports
26 import zmq
26 import zmq
27 from zmq.eventloop import ioloop
27 from zmq.eventloop import ioloop
28
28
29 # IPython imports
29 # IPython imports
30 from IPython.core.ultratb import FormattedTB
30 from IPython.core.ultratb import FormattedTB
31 from IPython.core.application import (
31 from IPython.core.application import (
32 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
32 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
33 )
33 )
34 from IPython.utils import io
34 from IPython.utils import io
35 from IPython.utils.localinterfaces import LOCALHOST
35 from IPython.utils.localinterfaces import LOCALHOST
36 from IPython.utils.path import filefind
36 from IPython.utils.path import filefind
37 from IPython.utils.py3compat import str_to_bytes
37 from IPython.utils.py3compat import str_to_bytes
38 from IPython.utils.traitlets import (
38 from IPython.utils.traitlets import (
39 Any, Instance, Dict, Unicode, Integer, Bool, CaselessStrEnum,
39 Any, Instance, Dict, Unicode, Integer, Bool, CaselessStrEnum,
40 DottedObjectName,
40 DottedObjectName,
41 )
41 )
42 from IPython.utils.importstring import import_item
42 from IPython.utils.importstring import import_item
43 # local imports
43 # local imports
44 from IPython.zmq.entry_point import write_connection_file
44 from IPython.zmq.entry_point import write_connection_file
45 from IPython.zmq.heartbeat import Heartbeat
45 from IPython.zmq.heartbeat import Heartbeat
46 from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
46 from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
47 from IPython.zmq.session import (
47 from IPython.zmq.session import (
48 Session, session_flags, session_aliases, default_secure,
48 Session, session_flags, session_aliases, default_secure,
49 )
49 )
50
50
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Flags and Aliases
53 # Flags and Aliases
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56 kernel_aliases = dict(base_aliases)
56 kernel_aliases = dict(base_aliases)
57 kernel_aliases.update({
57 kernel_aliases.update({
58 'ip' : 'KernelApp.ip',
58 'ip' : 'KernelApp.ip',
59 'hb' : 'KernelApp.hb_port',
59 'hb' : 'KernelApp.hb_port',
60 'shell' : 'KernelApp.shell_port',
60 'shell' : 'KernelApp.shell_port',
61 'iopub' : 'KernelApp.iopub_port',
61 'iopub' : 'KernelApp.iopub_port',
62 'stdin' : 'KernelApp.stdin_port',
62 'stdin' : 'KernelApp.stdin_port',
63 'f' : 'KernelApp.connection_file',
63 'f' : 'KernelApp.connection_file',
64 'parent': 'KernelApp.parent',
64 'parent': 'KernelApp.parent',
65 'transport': 'KernelApp.transport',
65 'transport': 'KernelApp.transport',
66 })
66 })
67 if sys.platform.startswith('win'):
67 if sys.platform.startswith('win'):
68 kernel_aliases['interrupt'] = 'KernelApp.interrupt'
68 kernel_aliases['interrupt'] = 'KernelApp.interrupt'
69
69
70 kernel_flags = dict(base_flags)
70 kernel_flags = dict(base_flags)
71 kernel_flags.update({
71 kernel_flags.update({
72 'no-stdout' : (
72 'no-stdout' : (
73 {'KernelApp' : {'no_stdout' : True}},
73 {'KernelApp' : {'no_stdout' : True}},
74 "redirect stdout to the null device"),
74 "redirect stdout to the null device"),
75 'no-stderr' : (
75 'no-stderr' : (
76 {'KernelApp' : {'no_stderr' : True}},
76 {'KernelApp' : {'no_stderr' : True}},
77 "redirect stderr to the null device"),
77 "redirect stderr to the null device"),
78 })
78 })
79
79
80 # inherit flags&aliases for Sessions
80 # inherit flags&aliases for Sessions
81 kernel_aliases.update(session_aliases)
81 kernel_aliases.update(session_aliases)
82 kernel_flags.update(session_flags)
82 kernel_flags.update(session_flags)
83
83
84
84
85
85
86 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
87 # Application class for starting a Kernel
87 # Application class for starting a Kernel
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89
89
90 class KernelApp(BaseIPythonApplication):
90 class KernelApp(BaseIPythonApplication):
91 name='ipkernel'
91 name='ipkernel'
92 aliases = Dict(kernel_aliases)
92 aliases = Dict(kernel_aliases)
93 flags = Dict(kernel_flags)
93 flags = Dict(kernel_flags)
94 classes = [Session]
94 classes = [Session]
95 # the kernel class, as an importstring
95 # the kernel class, as an importstring
96 kernel_class = DottedObjectName('IPython.zmq.ipkernel.Kernel')
96 kernel_class = DottedObjectName('IPython.zmq.ipkernel.Kernel')
97 kernel = Any()
97 kernel = Any()
98 poller = Any() # don't restrict this even though current pollers are all Threads
98 poller = Any() # don't restrict this even though current pollers are all Threads
99 heartbeat = Instance(Heartbeat)
99 heartbeat = Instance(Heartbeat)
100 session = Instance('IPython.zmq.session.Session')
100 session = Instance('IPython.zmq.session.Session')
101 ports = Dict()
101 ports = Dict()
102
102
103 # inherit config file name from parent:
103 # inherit config file name from parent:
104 parent_appname = Unicode(config=True)
104 parent_appname = Unicode(config=True)
105 def _parent_appname_changed(self, name, old, new):
105 def _parent_appname_changed(self, name, old, new):
106 if self.config_file_specified:
106 if self.config_file_specified:
107 # it was manually specified, ignore
107 # it was manually specified, ignore
108 return
108 return
109 self.config_file_name = new.replace('-','_') + u'_config.py'
109 self.config_file_name = new.replace('-','_') + u'_config.py'
110 # don't let this count as specifying the config file
110 # don't let this count as specifying the config file
111 self.config_file_specified = False
111 self.config_file_specified = False
112
112
113 # connection info:
113 # connection info:
114 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
114 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
115 ip = Unicode(config=True,
115 ip = Unicode(config=True,
116 help="Set the IP or interface on which the kernel will listen.")
116 help="Set the IP or interface on which the kernel will listen.")
117 def _ip_default(self):
117 def _ip_default(self):
118 if self.transport == 'ipc':
118 if self.transport == 'ipc':
119 if self.connection_file:
119 if self.connection_file:
120 return os.path.splitext(self.abs_connection_file)[0] + '-ipc'
120 return os.path.splitext(self.abs_connection_file)[0] + '-ipc'
121 else:
121 else:
122 return 'kernel-ipc'
122 return 'kernel-ipc'
123 else:
123 else:
124 return LOCALHOST
124 return LOCALHOST
125 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
125 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
126 shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]")
126 shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]")
127 iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]")
127 iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]")
128 stdin_port = Integer(0, config=True, help="set the stdin (DEALER) port [default: random]")
128 stdin_port = Integer(0, config=True, help="set the stdin (DEALER) port [default: random]")
129 connection_file = Unicode('', config=True,
129 connection_file = Unicode('', config=True,
130 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
130 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
131
131
132 This file will contain the IP, ports, and authentication key needed to connect
132 This file will contain the IP, ports, and authentication key needed to connect
133 clients to this kernel. By default, this file will be created in the security dir
133 clients to this kernel. By default, this file will be created in the security dir
134 of the current profile, but can be specified by absolute path.
134 of the current profile, but can be specified by absolute path.
135 """)
135 """)
136 @property
136 @property
137 def abs_connection_file(self):
137 def abs_connection_file(self):
138 if os.path.basename(self.connection_file) == self.connection_file:
138 if os.path.basename(self.connection_file) == self.connection_file:
139 return os.path.join(self.profile_dir.security_dir, self.connection_file)
139 return os.path.join(self.profile_dir.security_dir, self.connection_file)
140 else:
140 else:
141 return self.connection_file
141 return self.connection_file
142
142
143
143
144 # streams, etc.
144 # streams, etc.
145 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
145 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
146 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
146 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
147 outstream_class = DottedObjectName('IPython.zmq.iostream.OutStream',
147 outstream_class = DottedObjectName('IPython.zmq.iostream.OutStream',
148 config=True, help="The importstring for the OutStream factory")
148 config=True, help="The importstring for the OutStream factory")
149 displayhook_class = DottedObjectName('IPython.zmq.displayhook.ZMQDisplayHook',
149 displayhook_class = DottedObjectName('IPython.zmq.displayhook.ZMQDisplayHook',
150 config=True, help="The importstring for the DisplayHook factory")
150 config=True, help="The importstring for the DisplayHook factory")
151
151
152 # polling
152 # polling
153 parent = Integer(0, config=True,
153 parent = Integer(0, config=True,
154 help="""kill this process if its parent dies. On Windows, the argument
154 help="""kill this process if its parent dies. On Windows, the argument
155 specifies the HANDLE of the parent process, otherwise it is simply boolean.
155 specifies the HANDLE of the parent process, otherwise it is simply boolean.
156 """)
156 """)
157 interrupt = Integer(0, config=True,
157 interrupt = Integer(0, config=True,
158 help="""ONLY USED ON WINDOWS
158 help="""ONLY USED ON WINDOWS
159 Interrupt this process when the parent is signaled.
159 Interrupt this process when the parent is signaled.
160 """)
160 """)
161
161
162 def init_crash_handler(self):
162 def init_crash_handler(self):
163 # Install minimal exception handling
163 # Install minimal exception handling
164 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
164 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
165 ostream=sys.__stdout__)
165 ostream=sys.__stdout__)
166
166
167 def init_poller(self):
167 def init_poller(self):
168 if sys.platform == 'win32':
168 if sys.platform == 'win32':
169 if self.interrupt or self.parent:
169 if self.interrupt or self.parent:
170 self.poller = ParentPollerWindows(self.interrupt, self.parent)
170 self.poller = ParentPollerWindows(self.interrupt, self.parent)
171 elif self.parent:
171 elif self.parent:
172 self.poller = ParentPollerUnix()
172 self.poller = ParentPollerUnix()
173
173
174 def _bind_socket(self, s, port):
174 def _bind_socket(self, s, port):
175 iface = '%s://%s' % (self.transport, self.ip)
175 iface = '%s://%s' % (self.transport, self.ip)
176 if self.transport == 'tcp':
176 if self.transport == 'tcp':
177 if port <= 0:
177 if port <= 0:
178 port = s.bind_to_random_port(iface)
178 port = s.bind_to_random_port(iface)
179 else:
179 else:
180 s.bind("tcp://%s:%i" % (self.ip, port))
180 s.bind("tcp://%s:%i" % (self.ip, port))
181 elif self.transport == 'ipc':
181 elif self.transport == 'ipc':
182 if port <= 0:
182 if port <= 0:
183 for port in range(1,1024):
183 port = 1
184 path = "%s-%i" % (self.ip, port)
185 while os.path.exists(path):
186 port = port + 1
184 path = "%s-%i" % (self.ip, port)
187 path = "%s-%i" % (self.ip, port)
185 if not os.path.exists(path):
186 break
187 else:
188 else:
188 path = "%s-%i" % (self.ip, port)
189 path = "%s-%i" % (self.ip, port)
189 s.bind("ipc://%s" % path)
190 s.bind("ipc://%s" % path)
190 return port
191 return port
191
192
192 def load_connection_file(self):
193 def load_connection_file(self):
193 """load ip/port/hmac config from JSON connection file"""
194 """load ip/port/hmac config from JSON connection file"""
194 try:
195 try:
195 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
196 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
196 except IOError:
197 except IOError:
197 self.log.debug("Connection file not found: %s", self.connection_file)
198 self.log.debug("Connection file not found: %s", self.connection_file)
198 # This means I own it, so I will clean it up:
199 # This means I own it, so I will clean it up:
199 atexit.register(self.cleanup_connection_file)
200 atexit.register(self.cleanup_connection_file)
200 return
201 return
201 self.log.debug(u"Loading connection file %s", fname)
202 self.log.debug(u"Loading connection file %s", fname)
202 with open(fname) as f:
203 with open(fname) as f:
203 s = f.read()
204 s = f.read()
204 cfg = json.loads(s)
205 cfg = json.loads(s)
205 self.transport = cfg.get('transport', self.transport)
206 self.transport = cfg.get('transport', self.transport)
206 if self.ip == self._ip_default() and 'ip' in cfg:
207 if self.ip == self._ip_default() and 'ip' in cfg:
207 # not overridden by config or cl_args
208 # not overridden by config or cl_args
208 self.ip = cfg['ip']
209 self.ip = cfg['ip']
209 for channel in ('hb', 'shell', 'iopub', 'stdin'):
210 for channel in ('hb', 'shell', 'iopub', 'stdin'):
210 name = channel + '_port'
211 name = channel + '_port'
211 if getattr(self, name) == 0 and name in cfg:
212 if getattr(self, name) == 0 and name in cfg:
212 # not overridden by config or cl_args
213 # not overridden by config or cl_args
213 setattr(self, name, cfg[name])
214 setattr(self, name, cfg[name])
214 if 'key' in cfg:
215 if 'key' in cfg:
215 self.config.Session.key = str_to_bytes(cfg['key'])
216 self.config.Session.key = str_to_bytes(cfg['key'])
216
217
217 def write_connection_file(self):
218 def write_connection_file(self):
218 """write connection info to JSON file"""
219 """write connection info to JSON file"""
219 cf = self.abs_connection_file
220 cf = self.abs_connection_file
220 self.log.debug("Writing connection file: %s", cf)
221 self.log.debug("Writing connection file: %s", cf)
221 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
222 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
222 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
223 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
223 iopub_port=self.iopub_port)
224 iopub_port=self.iopub_port)
224
225
225 def cleanup_connection_file(self):
226 def cleanup_connection_file(self):
226 cf = self.abs_connection_file
227 cf = self.abs_connection_file
227 self.log.debug("Cleaning up connection file: %s", cf)
228 self.log.debug("Cleaning up connection file: %s", cf)
228 try:
229 try:
229 os.remove(cf)
230 os.remove(cf)
230 except (IOError, OSError):
231 except (IOError, OSError):
231 pass
232 pass
232
233
233 self.cleanup_ipc_files()
234 self.cleanup_ipc_files()
234
235
235 def cleanup_ipc_files(self):
236 def cleanup_ipc_files(self):
236 """cleanup ipc files if we wrote them"""
237 """cleanup ipc files if we wrote them"""
237 if self.transport != 'ipc':
238 if self.transport != 'ipc':
238 return
239 return
239 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port):
240 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port):
240 ipcfile = "%s-%i" % (self.ip, port)
241 ipcfile = "%s-%i" % (self.ip, port)
241 try:
242 try:
242 os.remove(ipcfile)
243 os.remove(ipcfile)
243 except (IOError, OSError):
244 except (IOError, OSError):
244 pass
245 pass
245
246
246 def init_connection_file(self):
247 def init_connection_file(self):
247 if not self.connection_file:
248 if not self.connection_file:
248 self.connection_file = "kernel-%s.json"%os.getpid()
249 self.connection_file = "kernel-%s.json"%os.getpid()
249 try:
250 try:
250 self.load_connection_file()
251 self.load_connection_file()
251 except Exception:
252 except Exception:
252 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
253 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
253 self.exit(1)
254 self.exit(1)
254
255
255 def init_sockets(self):
256 def init_sockets(self):
256 # Create a context, a session, and the kernel sockets.
257 # Create a context, a session, and the kernel sockets.
257 self.log.info("Starting the kernel at pid: %i", os.getpid())
258 self.log.info("Starting the kernel at pid: %i", os.getpid())
258 context = zmq.Context.instance()
259 context = zmq.Context.instance()
259 # Uncomment this to try closing the context.
260 # Uncomment this to try closing the context.
260 # atexit.register(context.term)
261 # atexit.register(context.term)
261
262
262 self.shell_socket = context.socket(zmq.ROUTER)
263 self.shell_socket = context.socket(zmq.ROUTER)
263 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
264 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
264 self.log.debug("shell ROUTER Channel on port: %i"%self.shell_port)
265 self.log.debug("shell ROUTER Channel on port: %i"%self.shell_port)
265
266
266 self.iopub_socket = context.socket(zmq.PUB)
267 self.iopub_socket = context.socket(zmq.PUB)
267 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
268 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
268 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
269 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
269
270
270 self.stdin_socket = context.socket(zmq.ROUTER)
271 self.stdin_socket = context.socket(zmq.ROUTER)
271 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
272 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
272 self.log.debug("stdin ROUTER Channel on port: %i"%self.stdin_port)
273 self.log.debug("stdin ROUTER Channel on port: %i"%self.stdin_port)
273
274
274 def init_heartbeat(self):
275 def init_heartbeat(self):
275 """start the heart beating"""
276 """start the heart beating"""
276 # heartbeat doesn't share context, because it mustn't be blocked
277 # heartbeat doesn't share context, because it mustn't be blocked
277 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
278 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
278 hb_ctx = zmq.Context()
279 hb_ctx = zmq.Context()
279 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
280 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
280 self.hb_port = self.heartbeat.port
281 self.hb_port = self.heartbeat.port
281 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
282 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
282 self.heartbeat.start()
283 self.heartbeat.start()
283
284
284 # Helper to make it easier to connect to an existing kernel.
285 # Helper to make it easier to connect to an existing kernel.
285 # set log-level to critical, to make sure it is output
286 # set log-level to critical, to make sure it is output
286 self.log.critical("To connect another client to this kernel, use:")
287 self.log.critical("To connect another client to this kernel, use:")
287
288
288 def log_connection_info(self):
289 def log_connection_info(self):
289 """display connection info, and store ports"""
290 """display connection info, and store ports"""
290 basename = os.path.basename(self.connection_file)
291 basename = os.path.basename(self.connection_file)
291 if basename == self.connection_file or \
292 if basename == self.connection_file or \
292 os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
293 os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
293 # use shortname
294 # use shortname
294 tail = basename
295 tail = basename
295 if self.profile != 'default':
296 if self.profile != 'default':
296 tail += " --profile %s" % self.profile
297 tail += " --profile %s" % self.profile
297 else:
298 else:
298 tail = self.connection_file
299 tail = self.connection_file
299 self.log.critical("--existing %s", tail)
300 self.log.critical("--existing %s", tail)
300
301
301
302
302 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
303 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
303 stdin=self.stdin_port, hb=self.hb_port)
304 stdin=self.stdin_port, hb=self.hb_port)
304
305
305 def init_session(self):
306 def init_session(self):
306 """create our session object"""
307 """create our session object"""
307 default_secure(self.config)
308 default_secure(self.config)
308 self.session = Session(config=self.config, username=u'kernel')
309 self.session = Session(config=self.config, username=u'kernel')
309
310
310 def init_blackhole(self):
311 def init_blackhole(self):
311 """redirects stdout/stderr to devnull if necessary"""
312 """redirects stdout/stderr to devnull if necessary"""
312 if self.no_stdout or self.no_stderr:
313 if self.no_stdout or self.no_stderr:
313 blackhole = open(os.devnull, 'w')
314 blackhole = open(os.devnull, 'w')
314 if self.no_stdout:
315 if self.no_stdout:
315 sys.stdout = sys.__stdout__ = blackhole
316 sys.stdout = sys.__stdout__ = blackhole
316 if self.no_stderr:
317 if self.no_stderr:
317 sys.stderr = sys.__stderr__ = blackhole
318 sys.stderr = sys.__stderr__ = blackhole
318
319
319 def init_io(self):
320 def init_io(self):
320 """Redirect input streams and set a display hook."""
321 """Redirect input streams and set a display hook."""
321 if self.outstream_class:
322 if self.outstream_class:
322 outstream_factory = import_item(str(self.outstream_class))
323 outstream_factory = import_item(str(self.outstream_class))
323 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
324 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
324 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
325 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
325 if self.displayhook_class:
326 if self.displayhook_class:
326 displayhook_factory = import_item(str(self.displayhook_class))
327 displayhook_factory = import_item(str(self.displayhook_class))
327 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
328 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
328
329
329 def init_signal(self):
330 def init_signal(self):
330 signal.signal(signal.SIGINT, signal.SIG_IGN)
331 signal.signal(signal.SIGINT, signal.SIG_IGN)
331
332
332 def init_kernel(self):
333 def init_kernel(self):
333 """Create the Kernel object itself"""
334 """Create the Kernel object itself"""
334 kernel_factory = import_item(str(self.kernel_class))
335 kernel_factory = import_item(str(self.kernel_class))
335 self.kernel = kernel_factory(config=self.config, session=self.session,
336 self.kernel = kernel_factory(config=self.config, session=self.session,
336 shell_socket=self.shell_socket,
337 shell_socket=self.shell_socket,
337 iopub_socket=self.iopub_socket,
338 iopub_socket=self.iopub_socket,
338 stdin_socket=self.stdin_socket,
339 stdin_socket=self.stdin_socket,
339 log=self.log
340 log=self.log
340 )
341 )
341 self.kernel.record_ports(self.ports)
342 self.kernel.record_ports(self.ports)
342
343
343 @catch_config_error
344 @catch_config_error
344 def initialize(self, argv=None):
345 def initialize(self, argv=None):
345 super(KernelApp, self).initialize(argv)
346 super(KernelApp, self).initialize(argv)
346 self.init_blackhole()
347 self.init_blackhole()
347 self.init_connection_file()
348 self.init_connection_file()
348 self.init_session()
349 self.init_session()
349 self.init_poller()
350 self.init_poller()
350 self.init_sockets()
351 self.init_sockets()
351 self.init_heartbeat()
352 self.init_heartbeat()
352 # writing/displaying connection info must be *after* init_sockets/heartbeat
353 # writing/displaying connection info must be *after* init_sockets/heartbeat
353 self.log_connection_info()
354 self.log_connection_info()
354 self.write_connection_file()
355 self.write_connection_file()
355 self.init_io()
356 self.init_io()
356 self.init_signal()
357 self.init_signal()
357 self.init_kernel()
358 self.init_kernel()
358 # flush stdout/stderr, so that anything written to these streams during
359 # flush stdout/stderr, so that anything written to these streams during
359 # initialization do not get associated with the first execution request
360 # initialization do not get associated with the first execution request
360 sys.stdout.flush()
361 sys.stdout.flush()
361 sys.stderr.flush()
362 sys.stderr.flush()
362
363
363 def start(self):
364 def start(self):
364 if self.poller is not None:
365 if self.poller is not None:
365 self.poller.start()
366 self.poller.start()
366 self.kernel.start()
367 self.kernel.start()
367 try:
368 try:
368 ioloop.IOLoop.instance().start()
369 ioloop.IOLoop.instance().start()
369 except KeyboardInterrupt:
370 except KeyboardInterrupt:
370 pass
371 pass
371
372
General Comments 0
You need to be logged in to leave comments. Login now