##// 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 if __name__ == '__main__':
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 import signal
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.
68 # Create a KernelManager.
73 parser = ArgumentParser()
69 kernel_manager = QtKernelManager()
74 parser.add_argument('--ip', type=str, default='127.0.0.1',
70 kernel_manager.start_kernel()
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))
86 kernel_manager.start_listening()
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 app = QtGui.QApplication([])
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 widget = IPythonWidget()
89 widget = IPythonWidget()
91 widget.kernel_manager = kernel_manager
90 widget.kernel_manager = kernel_manager
92 widget.setWindowTitle('Python')
91 widget.setWindowTitle('Python')
@@ -94,3 +93,4 b" if __name__ == '__main__':"
94 widget.show()
93 widget.show()
95 app.exec_()
94 app.exec_()
96
95
96
@@ -22,6 +22,7 b' from code import CommandCompiler'
22 import zmq
22 import zmq
23
23
24 # Local imports.
24 # Local imports.
25 from IPython.external.argparse import ArgumentParser
25 from session import Session, Message, extract_header
26 from session import Session, Message, extract_header
26 from completer import KernelCompleter
27 from completer import KernelCompleter
27
28
@@ -282,23 +283,33 b' def bind_port(socket, ip, port):'
282 socket.bind(connection)
283 socket.bind(connection)
283 return port
284 return port
284
285
285 def main(ip='127.0.0.1', rep_port=-1, pub_port=-1):
286 def main():
286 """ Start a kernel on 'ip' (default localhost) at the specified ports. If
287 """ Main entry point for launching a kernel.
287 ports are not specified, they are chosen at random.
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 print >>sys.__stdout__, "Starting the kernel..."
300 print >>sys.__stdout__, "Starting the kernel..."
290
291 context = zmq.Context()
301 context = zmq.Context()
292 session = Session(username=u'kernel')
302 session = Session(username=u'kernel')
293
303
294 reply_socket = context.socket(zmq.XREP)
304 reply_socket = context.socket(zmq.XREP)
295 rep_port = bind_port(reply_socket, ip, rep_port)
305 xrep_port = bind_port(reply_socket, namespace.ip, namespace.xrep)
296 print >>sys.__stdout__, "XREP Channel on port", rep_port
306 print >>sys.__stdout__, "XREP Channel on port", xrep_port
297
307
298 pub_socket = context.socket(zmq.PUB)
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 print >>sys.__stdout__, "PUB Channel on port", pub_port
310 print >>sys.__stdout__, "PUB Channel on port", pub_port
301
311
312 # Redirect input streams and set a display hook.
302 sys.stdout = OutStream(session, pub_socket, u'stdout')
313 sys.stdout = OutStream(session, pub_socket, u'stdout')
303 sys.stderr = OutStream(session, pub_socket, u'stderr')
314 sys.stderr = OutStream(session, pub_socket, u'stderr')
304 sys.displayhook = DisplayHook(session, pub_socket)
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 print >>sys.__stdout__, "Use Ctrl-\\ (NOT Ctrl-C!) to terminate."
324 print >>sys.__stdout__, "Use Ctrl-\\ (NOT Ctrl-C!) to terminate."
314 kernel.start()
325 kernel.start()
315
326
316 def launch_kernel():
327 def launch_kernel(xrep_port=-1, pub_port=-1):
317 """ Launches a kernel on this machine and binds its to channels to open
328 """ Launches a localhost kernel, binding to the specified ports. For any
318 ports as it determined by the OS.
329 port that is left unspecified, a port is chosen by the operating system.
319
330
320 Returns a tuple of form:
331 Returns a tuple of form:
321 (kernel_process [Popen], rep_port [int], sub_port [int])
332 (kernel_process [Popen], rep_port [int], sub_port [int])
@@ -323,9 +334,10 b' def launch_kernel():'
323 import socket
334 import socket
324 from subprocess import Popen
335 from subprocess import Popen
325
336
326 # Find some open ports.
337 # Find open ports as necessary.
327 ports = []
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 sock = socket.socket()
341 sock = socket.socket()
330 sock.bind(('', 0))
342 sock.bind(('', 0))
331 ports.append(sock)
343 ports.append(sock)
@@ -333,17 +345,17 b' def launch_kernel():'
333 port = sock.getsockname()[1]
345 port = sock.getsockname()[1]
334 sock.close()
346 sock.close()
335 ports[i] = port
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 # Spawn a kernel.
353 # Spawn a kernel.
339 command = 'from IPython.zmq.kernel import main;' \
354 command = 'from IPython.zmq.kernel import main; main()'
340 'main(rep_port=%i, pub_port=%i)'
355 proc = Popen([ sys.executable, '-c', command,
341 proc = Popen([sys.executable, '-c', command % (rep_port, sub_port)])
356 '--xrep', str(xrep_port), '--pub', str(pub_port) ])
342
357 return proc, xrep_port, pub_port
343 return proc, rep_port, sub_port
344
358
345
359
346 if __name__ == '__main__':
360 if __name__ == '__main__':
347 base_port = 5575
361 main()
348 main(rep_port = base_port,
349 pub_port = base_port + 1)
@@ -6,6 +6,7 b' TODO: Create logger to handle debugging and console messages.'
6
6
7 # Standard library imports.
7 # Standard library imports.
8 from Queue import Queue, Empty
8 from Queue import Queue, Empty
9 from subprocess import Popen
9 from threading import Thread
10 from threading import Thread
10 import time
11 import time
11 import traceback
12 import traceback
@@ -18,8 +19,12 b' from zmq.eventloop import ioloop'
18 # Local imports.
19 # Local imports.
19 from IPython.utils.traitlets import HasTraits, Any, Bool, Int, Instance, Str, \
20 from IPython.utils.traitlets import HasTraits, Any, Bool, Int, Instance, Str, \
20 Type
21 Type
22 from kernel import launch_kernel
21 from session import Session
23 from session import Session
22
24
25 # Constants.
26 LOCALHOST = '127.0.0.1'
27
23
28
24 class MissingHandlerError(Exception):
29 class MissingHandlerError(Exception):
25 pass
30 pass
@@ -49,19 +54,22 b' class ZmqSocketChannel(Thread):'
49 Thread.__init__(self)
54 Thread.__init__(self)
50
55
51 def get_address(self):
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 return self._address
60 return self._address
55
61
56 def set_adresss(self, address):
62 def set_adresss(self, address):
57 """ Set the channel's address. Should be a tuple of form:
63 """ Set the channel's address. Should be a tuple of form:
58 (ip address [str], port [int])
64 (ip address [str], port [int]).
59 or 'None' to indicate that no address has been specified.
65 or None, in which case the address is reset to its default value.
60 """
66 """
61 # FIXME: Validate address.
67 # FIXME: Validate address.
62 if self.is_alive():
68 if self.is_alive():
63 raise RuntimeError("Cannot set address on a running channel!")
69 raise RuntimeError("Cannot set address on a running channel!")
64 else:
70 else:
71 if address is None:
72 address = (LOCALHOST, -1)
65 self._address = address
73 self._address = address
66
74
67 address = property(get_address, set_adresss)
75 address = property(get_address, set_adresss)
@@ -314,6 +322,7 b' class KernelManager(HasTraits):'
314 rep_channel_class = Type(RepSocketChannel)
322 rep_channel_class = Type(RepSocketChannel)
315
323
316 # Protected traits.
324 # Protected traits.
325 _kernel = Instance(Popen)
317 _sub_channel = Any
326 _sub_channel = Any
318 _xreq_channel = Any
327 _xreq_channel = Any
319 _rep_channel = Any
328 _rep_channel = Any
@@ -347,17 +356,26 b' class KernelManager(HasTraits):'
347 self.rep_channel.stop()
356 self.rep_channel.stop()
348
357
349 def start_kernel(self):
358 def start_kernel(self):
350 """Start a localhost kernel. If ports have been specified, use them.
359 """Start a localhost kernel. If ports have been specified via the
351 Otherwise, choose an open port at random.
360 address attributes, use them. Otherwise, choose open ports at random.
352 """
361 """
353 # TODO: start a kernel.
362 xreq, sub = self.xreq_address, self.sub_address
354 self.start_listening()
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 def kill_kernel(self):
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.
376 if self._kernel:
360 self.stop_listening()
377 self._kernel.kill()
378 self._kernel = None
361
379
362 @property
380 @property
363 def is_alive(self):
381 def is_alive(self):
General Comments 0
You need to be logged in to leave comments. Login now