##// END OF EJS Templates
* Implemented a proper main() function for kernel.py that reads command line input....
epatters -
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, rep_port)
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_port)
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 some open ports.
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 'None' to indicate that no address has been specified.
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, use them.
351 Otherwise, choose an open port at random.
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.stop_listening()
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