Show More
@@ -62,31 +62,30 b' class IPythonWidget(FrontendWidget):' | |||
|
62 | 62 | |
|
63 | 63 | |
|
64 | 64 | if __name__ == '__main__': |
|
65 | from IPython.external.argparse import ArgumentParser | |
|
66 | from IPython.frontend.qt.kernelmanager import QtKernelManager | |
|
67 | ||
|
68 | # Don't let Qt swallow KeyboardInterupts. | |
|
69 | 65 | import signal |
|
70 | signal.signal(signal.SIGINT, signal.SIG_DFL) | |
|
66 | from IPython.frontend.qt.kernelmanager import QtKernelManager | |
|
71 | 67 | |
|
72 | # Parse command line arguments. | |
|
73 | parser = ArgumentParser() | |
|
74 | parser.add_argument('--ip', type=str, default='127.0.0.1', | |
|
75 | help='set the kernel\'s IP address [default localhost]') | |
|
76 | parser.add_argument('--xreq', type=int, metavar='PORT', default=5575, | |
|
77 | help='set the XREQ Channel port [default %(default)i]') | |
|
78 | parser.add_argument('--sub', type=int, metavar='PORT', default=5576, | |
|
79 | help='set the SUB Channel port [default %(default)i]') | |
|
80 | namespace = parser.parse_args() | |
|
81 | ||
|
82 | # Create KernelManager | |
|
83 | ip = namespace.ip | |
|
84 | kernel_manager = QtKernelManager(xreq_address = (ip, namespace.xreq), | |
|
85 | sub_address = (ip, namespace.sub)) | |
|
68 | # Create a KernelManager. | |
|
69 | kernel_manager = QtKernelManager() | |
|
70 | kernel_manager.start_kernel() | |
|
86 | 71 | kernel_manager.start_listening() |
|
87 | 72 | |
|
88 | # Launch application | |
|
73 | # Don't let Qt or ZMQ swallow KeyboardInterupts. | |
|
74 | # FIXME: Gah, ZMQ swallows even custom signal handlers. So for now we leave | |
|
75 | # behind a kernel process when Ctrl-C is pressed. | |
|
76 | #def sigint_hook(signum, frame): | |
|
77 | # QtGui.qApp.quit() | |
|
78 | #signal.signal(signal.SIGINT, sigint_hook) | |
|
79 | signal.signal(signal.SIGINT, signal.SIG_DFL) | |
|
80 | ||
|
81 | # Create the application, making sure to clean up nicely when we exit. | |
|
89 | 82 | app = QtGui.QApplication([]) |
|
83 | def quit_hook(): | |
|
84 | kernel_manager.stop_listening() | |
|
85 | kernel_manager.kill_kernel() | |
|
86 | app.aboutToQuit.connect(quit_hook) | |
|
87 | ||
|
88 | # Launch the application. | |
|
90 | 89 | widget = IPythonWidget() |
|
91 | 90 | widget.kernel_manager = kernel_manager |
|
92 | 91 | widget.setWindowTitle('Python') |
@@ -94,3 +93,4 b" if __name__ == '__main__':" | |||
|
94 | 93 | widget.show() |
|
95 | 94 | app.exec_() |
|
96 | 95 | |
|
96 |
@@ -22,6 +22,7 b' from code import CommandCompiler' | |||
|
22 | 22 | import zmq |
|
23 | 23 | |
|
24 | 24 | # Local imports. |
|
25 | from IPython.external.argparse import ArgumentParser | |
|
25 | 26 | from session import Session, Message, extract_header |
|
26 | 27 | from completer import KernelCompleter |
|
27 | 28 | |
@@ -282,23 +283,33 b' def bind_port(socket, ip, port):' | |||
|
282 | 283 | socket.bind(connection) |
|
283 | 284 | return port |
|
284 | 285 | |
|
285 | def main(ip='127.0.0.1', rep_port=-1, pub_port=-1): | |
|
286 | """ Start a kernel on 'ip' (default localhost) at the specified ports. If | |
|
287 | ports are not specified, they are chosen at random. | |
|
286 | def main(): | |
|
287 | """ Main entry point for launching a kernel. | |
|
288 | 288 | """ |
|
289 | # Parse command line arguments. | |
|
290 | parser = ArgumentParser() | |
|
291 | parser.add_argument('--ip', type=str, default='127.0.0.1', | |
|
292 | help='set the kernel\'s IP address [default: local]') | |
|
293 | parser.add_argument('--xrep', type=int, metavar='PORT', default=-1, | |
|
294 | help='set the XREP Channel port [default: random]') | |
|
295 | parser.add_argument('--pub', type=int, metavar='PORT', default=-1, | |
|
296 | help='set the PUB Channel port [default: random]') | |
|
297 | namespace = parser.parse_args() | |
|
298 | ||
|
299 | # Create context, session, and kernel sockets. | |
|
289 | 300 | print >>sys.__stdout__, "Starting the kernel..." |
|
290 | ||
|
291 | 301 | context = zmq.Context() |
|
292 | 302 | session = Session(username=u'kernel') |
|
293 | 303 | |
|
294 | 304 | reply_socket = context.socket(zmq.XREP) |
|
295 |
rep_port = bind_port(reply_socket, ip, |
|
|
296 | print >>sys.__stdout__, "XREP Channel on port", rep_port | |
|
305 | xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep) | |
|
306 | print >>sys.__stdout__, "XREP Channel on port", xrep_port | |
|
297 | 307 | |
|
298 | 308 | pub_socket = context.socket(zmq.PUB) |
|
299 |
pub_port = bind_port(pub_socket, ip, pub |
|
|
309 | pub_port = bind_port(pub_socket, namespace.ip, namespace.pub) | |
|
300 | 310 | print >>sys.__stdout__, "PUB Channel on port", pub_port |
|
301 | 311 | |
|
312 | # Redirect input streams and set a display hook. | |
|
302 | 313 | sys.stdout = OutStream(session, pub_socket, u'stdout') |
|
303 | 314 | sys.stderr = OutStream(session, pub_socket, u'stderr') |
|
304 | 315 | sys.displayhook = DisplayHook(session, pub_socket) |
@@ -313,9 +324,9 b" def main(ip='127.0.0.1', rep_port=-1, pub_port=-1):" | |||
|
313 | 324 | print >>sys.__stdout__, "Use Ctrl-\\ (NOT Ctrl-C!) to terminate." |
|
314 | 325 | kernel.start() |
|
315 | 326 | |
|
316 | def launch_kernel(): | |
|
317 | """ Launches a kernel on this machine and binds its to channels to open | |
|
318 | ports as it determined by the OS. | |
|
327 | def launch_kernel(xrep_port=-1, pub_port=-1): | |
|
328 | """ Launches a localhost kernel, binding to the specified ports. For any | |
|
329 | port that is left unspecified, a port is chosen by the operating system. | |
|
319 | 330 | |
|
320 | 331 | Returns a tuple of form: |
|
321 | 332 | (kernel_process [Popen], rep_port [int], sub_port [int]) |
@@ -323,9 +334,10 b' def launch_kernel():' | |||
|
323 | 334 | import socket |
|
324 | 335 | from subprocess import Popen |
|
325 | 336 | |
|
326 |
# Find |
|
|
337 | # Find open ports as necessary. | |
|
327 | 338 | ports = [] |
|
328 | for i in xrange(2): | |
|
339 | ports_needed = int(xrep_port < 0) + int(pub_port < 0) | |
|
340 | for i in xrange(ports_needed): | |
|
329 | 341 | sock = socket.socket() |
|
330 | 342 | sock.bind(('', 0)) |
|
331 | 343 | ports.append(sock) |
@@ -333,17 +345,17 b' def launch_kernel():' | |||
|
333 | 345 | port = sock.getsockname()[1] |
|
334 | 346 | sock.close() |
|
335 | 347 | ports[i] = port |
|
336 | rep_port, sub_port = ports | |
|
348 | if xrep_port < 0: | |
|
349 | xrep_port = ports.pop() | |
|
350 | if pub_port < 0: | |
|
351 | pub_port = ports.pop() | |
|
337 | 352 | |
|
338 | 353 | # Spawn a kernel. |
|
339 |
command = 'from IPython.zmq.kernel import main;' |
|
|
340 | 'main(rep_port=%i, pub_port=%i)' | |
|
341 | proc = Popen([sys.executable, '-c', command % (rep_port, sub_port)]) | |
|
342 | ||
|
343 | return proc, rep_port, sub_port | |
|
354 | command = 'from IPython.zmq.kernel import main; main()' | |
|
355 | proc = Popen([ sys.executable, '-c', command, | |
|
356 | '--xrep', str(xrep_port), '--pub', str(pub_port) ]) | |
|
357 | return proc, xrep_port, pub_port | |
|
344 | 358 | |
|
345 | 359 | |
|
346 | 360 | if __name__ == '__main__': |
|
347 | base_port = 5575 | |
|
348 | main(rep_port = base_port, | |
|
349 | pub_port = base_port + 1) | |
|
361 | main() |
@@ -6,6 +6,7 b' TODO: Create logger to handle debugging and console messages.' | |||
|
6 | 6 | |
|
7 | 7 | # Standard library imports. |
|
8 | 8 | from Queue import Queue, Empty |
|
9 | from subprocess import Popen | |
|
9 | 10 | from threading import Thread |
|
10 | 11 | import time |
|
11 | 12 | import traceback |
@@ -18,8 +19,12 b' from zmq.eventloop import ioloop' | |||
|
18 | 19 | # Local imports. |
|
19 | 20 | from IPython.utils.traitlets import HasTraits, Any, Bool, Int, Instance, Str, \ |
|
20 | 21 | Type |
|
22 | from kernel import launch_kernel | |
|
21 | 23 | from session import Session |
|
22 | 24 | |
|
25 | # Constants. | |
|
26 | LOCALHOST = '127.0.0.1' | |
|
27 | ||
|
23 | 28 | |
|
24 | 29 | class MissingHandlerError(Exception): |
|
25 | 30 | pass |
@@ -49,19 +54,22 b' class ZmqSocketChannel(Thread):' | |||
|
49 | 54 | Thread.__init__(self) |
|
50 | 55 | |
|
51 | 56 | def get_address(self): |
|
52 | """ Get the channel's address. | |
|
57 | """ Get the channel's address. By the default, a channel is on | |
|
58 | localhost with no port specified (a negative port number). | |
|
53 | 59 | """ |
|
54 | 60 | return self._address |
|
55 | 61 | |
|
56 | 62 | def set_adresss(self, address): |
|
57 | 63 | """ Set the channel's address. Should be a tuple of form: |
|
58 | (ip address [str], port [int]) | |
|
59 |
or |
|
|
64 | (ip address [str], port [int]). | |
|
65 | or None, in which case the address is reset to its default value. | |
|
60 | 66 | """ |
|
61 | 67 | # FIXME: Validate address. |
|
62 | 68 | if self.is_alive(): |
|
63 | 69 | raise RuntimeError("Cannot set address on a running channel!") |
|
64 | 70 | else: |
|
71 | if address is None: | |
|
72 | address = (LOCALHOST, -1) | |
|
65 | 73 | self._address = address |
|
66 | 74 | |
|
67 | 75 | address = property(get_address, set_adresss) |
@@ -314,6 +322,7 b' class KernelManager(HasTraits):' | |||
|
314 | 322 | rep_channel_class = Type(RepSocketChannel) |
|
315 | 323 | |
|
316 | 324 | # Protected traits. |
|
325 | _kernel = Instance(Popen) | |
|
317 | 326 | _sub_channel = Any |
|
318 | 327 | _xreq_channel = Any |
|
319 | 328 | _rep_channel = Any |
@@ -347,17 +356,26 b' class KernelManager(HasTraits):' | |||
|
347 | 356 | self.rep_channel.stop() |
|
348 | 357 | |
|
349 | 358 | def start_kernel(self): |
|
350 |
"""Start a localhost kernel. If ports have been specified |
|
|
351 |
Otherwise, choose |
|
|
359 | """Start a localhost kernel. If ports have been specified via the | |
|
360 | address attributes, use them. Otherwise, choose open ports at random. | |
|
352 | 361 | """ |
|
353 | # TODO: start a kernel. | |
|
354 | self.start_listening() | |
|
362 | xreq, sub = self.xreq_address, self.sub_address | |
|
363 | if xreq[0] != LOCALHOST or sub[0] != LOCALHOST: | |
|
364 | raise RuntimeError("Can only launch a kernel on localhost." | |
|
365 | "Make sure that the '*_address' attributes are " | |
|
366 | "configured properly.") | |
|
367 | ||
|
368 | self._kernel, xrep, pub = launch_kernel(xrep_port=xreq[1], | |
|
369 | pub_port=sub[1]) | |
|
370 | self.xreq_address = (LOCALHOST, xrep) | |
|
371 | self.sub_address = (LOCALHOST, pub) | |
|
355 | 372 | |
|
356 | 373 | def kill_kernel(self): |
|
357 | """Kill the running kernel. | |
|
374 | """Kill the running kernel, if there is one. | |
|
358 | 375 | """ |
|
359 | # TODO: kill the kernel. | |
|
360 |
self. |
|
|
376 | if self._kernel: | |
|
377 | self._kernel.kill() | |
|
378 | self._kernel = None | |
|
361 | 379 | |
|
362 | 380 | @property |
|
363 | 381 | def is_alive(self): |
General Comments 0
You need to be logged in to leave comments.
Login now