##// END OF EJS Templates
use logging instead of `print >>` in pykernel
MinRK -
Show More
@@ -1,213 +1,214 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.newapplication import (
28 from IPython.core.newapplication 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 from IPython.utils.importstring import import_item
34 from IPython.utils.importstring import import_item
35 # local imports
35 # local imports
36 from IPython.zmq.heartbeat import Heartbeat
36 from IPython.zmq.heartbeat import Heartbeat
37 from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
37 from IPython.zmq.parentpoller import ParentPollerUnix, ParentPollerWindows
38 from IPython.zmq.session import Session
38 from IPython.zmq.session import Session
39
39
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Flags and Aliases
42 # Flags and Aliases
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 kernel_aliases = dict(base_aliases)
45 kernel_aliases = dict(base_aliases)
46 kernel_aliases.update({
46 kernel_aliases.update({
47 'ip' : 'KernelApp.ip',
47 'ip' : 'KernelApp.ip',
48 'hb' : 'KernelApp.hb_port',
48 'hb' : 'KernelApp.hb_port',
49 'shell' : 'KernelApp.shell_port',
49 'shell' : 'KernelApp.shell_port',
50 'iopub' : 'KernelApp.iopub_port',
50 'iopub' : 'KernelApp.iopub_port',
51 'stdin' : 'KernelApp.stdin_port',
51 'stdin' : 'KernelApp.stdin_port',
52 'parent': 'KernelApp.parent',
52 'parent': 'KernelApp.parent',
53 })
53 })
54 if sys.platform.startswith('win'):
54 if sys.platform.startswith('win'):
55 kernel_aliases['interrupt'] = 'KernelApp.interrupt'
55 kernel_aliases['interrupt'] = 'KernelApp.interrupt'
56
56
57 kernel_flags = dict(base_flags)
57 kernel_flags = dict(base_flags)
58 kernel_flags.update({
58 kernel_flags.update({
59 'no-stdout' : (
59 'no-stdout' : (
60 {'KernelApp' : {'no_stdout' : True}},
60 {'KernelApp' : {'no_stdout' : True}},
61 "redirect stdout to the null device"),
61 "redirect stdout to the null device"),
62 'no-stderr' : (
62 'no-stderr' : (
63 {'KernelApp' : {'no_stderr' : True}},
63 {'KernelApp' : {'no_stderr' : True}},
64 "redirect stderr to the null device"),
64 "redirect stderr to the null device"),
65 })
65 })
66
66
67
67
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69 # Application class for starting a Kernel
69 # Application class for starting a Kernel
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71
71
72 class KernelApp(BaseIPythonApplication):
72 class KernelApp(BaseIPythonApplication):
73 name='pykernel'
73 name='pykernel'
74 aliases = Dict(kernel_aliases)
74 aliases = Dict(kernel_aliases)
75 flags = Dict(kernel_flags)
75 flags = Dict(kernel_flags)
76
76
77 # the kernel class, as an importstring
77 # the kernel class, as an importstring
78 kernel_class = Unicode('IPython.zmq.pykernel.Kernel')
78 kernel_class = Unicode('IPython.zmq.pykernel.Kernel')
79 kernel = Any()
79 kernel = Any()
80 poller = Any() # don't restrict this even though current pollers are all Threads
80 poller = Any() # don't restrict this even though current pollers are all Threads
81 heartbeat = Instance(Heartbeat)
81 heartbeat = Instance(Heartbeat)
82 session = Instance('IPython.zmq.session.Session')
82 session = Instance('IPython.zmq.session.Session')
83 ports = Dict()
83 ports = Dict()
84
84
85 # connection info:
85 # connection info:
86 ip = Unicode(LOCALHOST, config=True,
86 ip = Unicode(LOCALHOST, config=True,
87 help="Set the IP or interface on which the kernel will listen.")
87 help="Set the IP or interface on which the kernel will listen.")
88 hb_port = Int(0, config=True, help="set the heartbeat port [default: random]")
88 hb_port = Int(0, config=True, help="set the heartbeat port [default: random]")
89 shell_port = Int(0, config=True, help="set the shell (XREP) port [default: random]")
89 shell_port = Int(0, config=True, help="set the shell (XREP) port [default: random]")
90 iopub_port = Int(0, config=True, help="set the iopub (PUB) port [default: random]")
90 iopub_port = Int(0, config=True, help="set the iopub (PUB) port [default: random]")
91 stdin_port = Int(0, config=True, help="set the stdin (XREQ) port [default: random]")
91 stdin_port = Int(0, config=True, help="set the stdin (XREQ) port [default: random]")
92
92
93 # streams, etc.
93 # streams, etc.
94 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
94 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
95 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
95 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
96 outstream_class = Unicode('IPython.zmq.iostream.OutStream', config=True,
96 outstream_class = Unicode('IPython.zmq.iostream.OutStream', config=True,
97 help="The importstring for the OutStream factory")
97 help="The importstring for the OutStream factory")
98 displayhook_class = Unicode('IPython.zmq.displayhook.DisplayHook', config=True,
98 displayhook_class = Unicode('IPython.zmq.displayhook.DisplayHook', config=True,
99 help="The importstring for the DisplayHook factory")
99 help="The importstring for the DisplayHook factory")
100
100
101 # polling
101 # polling
102 parent = Int(0, config=True,
102 parent = Int(0, config=True,
103 help="""kill this process if its parent dies. On Windows, the argument
103 help="""kill this process if its parent dies. On Windows, the argument
104 specifies the HANDLE of the parent process, otherwise it is simply boolean.
104 specifies the HANDLE of the parent process, otherwise it is simply boolean.
105 """)
105 """)
106 interrupt = Int(0, config=True,
106 interrupt = Int(0, config=True,
107 help="""ONLY USED ON WINDOWS
107 help="""ONLY USED ON WINDOWS
108 Interrupt this process when the parent is signalled.
108 Interrupt this process when the parent is signalled.
109 """)
109 """)
110
110
111 def init_crash_handler(self):
111 def init_crash_handler(self):
112 # Install minimal exception handling
112 # Install minimal exception handling
113 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
113 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
114 ostream=sys.__stdout__)
114 ostream=sys.__stdout__)
115
115
116 def init_poller(self):
116 def init_poller(self):
117 if sys.platform == 'win32':
117 if sys.platform == 'win32':
118 if self.interrupt or self.parent:
118 if self.interrupt or self.parent:
119 self.poller = ParentPollerWindows(self.interrupt, self.parent)
119 self.poller = ParentPollerWindows(self.interrupt, self.parent)
120 elif self.parent:
120 elif self.parent:
121 self.poller = ParentPollerUnix()
121 self.poller = ParentPollerUnix()
122
122
123 def _bind_socket(self, s, port):
123 def _bind_socket(self, s, port):
124 iface = 'tcp://%s' % self.ip
124 iface = 'tcp://%s' % self.ip
125 if port <= 0:
125 if port <= 0:
126 port = s.bind_to_random_port(iface)
126 port = s.bind_to_random_port(iface)
127 else:
127 else:
128 s.bind(iface + ':%i'%port)
128 s.bind(iface + ':%i'%port)
129 return port
129 return port
130
130
131 def init_sockets(self):
131 def init_sockets(self):
132 # Create a context, a session, and the kernel sockets.
132 # Create a context, a session, and the kernel sockets.
133 io.raw_print("Starting the kernel at pid:", os.getpid())
133 io.raw_print("Starting the kernel at pid:", os.getpid())
134 context = zmq.Context.instance()
134 context = zmq.Context.instance()
135 # Uncomment this to try closing the context.
135 # Uncomment this to try closing the context.
136 # atexit.register(context.term)
136 # atexit.register(context.term)
137
137
138 self.shell_socket = context.socket(zmq.XREP)
138 self.shell_socket = context.socket(zmq.XREP)
139 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
139 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
140 self.log.debug("shell XREP Channel on port: %i"%self.shell_port)
140 self.log.debug("shell XREP Channel on port: %i"%self.shell_port)
141
141
142 self.iopub_socket = context.socket(zmq.PUB)
142 self.iopub_socket = context.socket(zmq.PUB)
143 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
143 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
144 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
144 self.log.debug("iopub PUB Channel on port: %i"%self.iopub_port)
145
145
146 self.stdin_socket = context.socket(zmq.XREQ)
146 self.stdin_socket = context.socket(zmq.XREQ)
147 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
147 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
148 self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
148 self.log.debug("stdin XREQ Channel on port: %i"%self.stdin_port)
149
149
150 self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
150 self.heartbeat = Heartbeat(context, (self.ip, self.hb_port))
151 self.hb_port = self.heartbeat.port
151 self.hb_port = self.heartbeat.port
152 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
152 self.log.debug("Heartbeat REP Channel on port: %i"%self.hb_port)
153
153
154 # Helper to make it easier to connect to an existing kernel, until we have
154 # Helper to make it easier to connect to an existing kernel, until we have
155 # single-port connection negotiation fully implemented.
155 # single-port connection negotiation fully implemented.
156 self.log.info("To connect another client to this kernel, use:")
156 self.log.info("To connect another client to this kernel, use:")
157 self.log.info("--external shell={0} iopub={1} stdin={2} hb={3}".format(
157 self.log.info("--external shell={0} iopub={1} stdin={2} hb={3}".format(
158 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port))
158 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port))
159
159
160
160
161 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
161 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
162 stdin=self.stdin_port, hb=self.hb_port)
162 stdin=self.stdin_port, hb=self.hb_port)
163
163
164 def init_session(self):
164 def init_session(self):
165 """create our session object"""
165 """create our session object"""
166 self.session = Session(username=u'kernel')
166 self.session = Session(username=u'kernel')
167
167
168 def init_io(self):
168 def init_io(self):
169 """redirects stdout/stderr, and installs a display hook"""
169 """redirects stdout/stderr, and installs a display hook"""
170 # Re-direct stdout/stderr, if necessary.
170 # Re-direct stdout/stderr, if necessary.
171 if self.no_stdout or self.no_stderr:
171 if self.no_stdout or self.no_stderr:
172 blackhole = file(os.devnull, 'w')
172 blackhole = file(os.devnull, 'w')
173 if self.no_stdout:
173 if self.no_stdout:
174 sys.stdout = sys.__stdout__ = blackhole
174 sys.stdout = sys.__stdout__ = blackhole
175 if self.no_stderr:
175 if self.no_stderr:
176 sys.stderr = sys.__stderr__ = blackhole
176 sys.stderr = sys.__stderr__ = blackhole
177
177
178 # Redirect input streams and set a display hook.
178 # Redirect input streams and set a display hook.
179
179
180 if self.outstream_class:
180 if self.outstream_class:
181 outstream_factory = import_item(str(self.outstream_class))
181 outstream_factory = import_item(str(self.outstream_class))
182 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
182 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
183 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
183 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
184 if self.displayhook_class:
184 if self.displayhook_class:
185 displayhook_factory = import_item(str(self.displayhook_class))
185 displayhook_factory = import_item(str(self.displayhook_class))
186 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
186 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
187
187
188 def init_kernel(self):
188 def init_kernel(self):
189 """Create the Kernel object itself"""
189 """Create the Kernel object itself"""
190 kernel_factory = import_item(str(self.kernel_class))
190 kernel_factory = import_item(str(self.kernel_class))
191 self.kernel = kernel_factory(config=self.config, session=self.session,
191 self.kernel = kernel_factory(config=self.config, session=self.session,
192 shell_socket=self.shell_socket,
192 shell_socket=self.shell_socket,
193 iopub_socket=self.iopub_socket,
193 iopub_socket=self.iopub_socket,
194 stdin_socket=self.stdin_socket,
194 stdin_socket=self.stdin_socket,
195 log=self.log
195 )
196 )
196 self.kernel.record_ports(self.ports)
197 self.kernel.record_ports(self.ports)
197
198
198 def initialize(self, argv=None):
199 def initialize(self, argv=None):
199 super(KernelApp, self).initialize(argv)
200 super(KernelApp, self).initialize(argv)
200 self.init_session()
201 self.init_session()
201 self.init_poller()
202 self.init_poller()
202 self.init_sockets()
203 self.init_sockets()
203 self.init_io()
204 self.init_io()
204 self.init_kernel()
205 self.init_kernel()
205
206
206 def start(self):
207 def start(self):
207 self.heartbeat.start()
208 self.heartbeat.start()
208 if self.poller is not None:
209 if self.poller is not None:
209 self.poller.start()
210 self.poller.start()
210 try:
211 try:
211 self.kernel.start()
212 self.kernel.start()
212 except KeyboardInterrupt:
213 except KeyboardInterrupt:
213 pass
214 pass
@@ -1,280 +1,278 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 # Standard library imports.
17 # Standard library imports.
18 import __builtin__
18 import __builtin__
19 from code import CommandCompiler
19 from code import CommandCompiler
20 import sys
20 import sys
21 import time
21 import time
22 import traceback
22 import traceback
23
23
24 # System library imports.
24 # System library imports.
25 import zmq
25 import zmq
26
26
27 # Local imports.
27 # Local imports.
28 from IPython.utils.traitlets import HasTraits, Instance, Dict, Float
28 from IPython.utils.traitlets import HasTraits, Instance, Dict, Float
29 from completer import KernelCompleter
29 from completer import KernelCompleter
30 from entry_point import base_launch_kernel
30 from entry_point import base_launch_kernel
31 from session import Session, Message
31 from session import Session, Message
32 from kernelapp import KernelApp
32 from kernelapp import KernelApp
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Main kernel class
35 # Main kernel class
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 class Kernel(HasTraits):
38 class Kernel(HasTraits):
39
39
40 # Private interface
40 # Private interface
41
41
42 # Time to sleep after flushing the stdout/err buffers in each execute
42 # Time to sleep after flushing the stdout/err buffers in each execute
43 # cycle. While this introduces a hard limit on the minimal latency of the
43 # cycle. While this introduces a hard limit on the minimal latency of the
44 # execute cycle, it helps prevent output synchronization problems for
44 # execute cycle, it helps prevent output synchronization problems for
45 # clients.
45 # clients.
46 # Units are in seconds. The minimum zmq latency on local host is probably
46 # Units are in seconds. The minimum zmq latency on local host is probably
47 # ~150 microseconds, set this to 500us for now. We may need to increase it
47 # ~150 microseconds, set this to 500us for now. We may need to increase it
48 # a little if it's not enough after more interactive testing.
48 # a little if it's not enough after more interactive testing.
49 _execute_sleep = Float(0.0005, config=True)
49 _execute_sleep = Float(0.0005, config=True)
50
50
51 # This is a dict of port number that the kernel is listening on. It is set
51 # This is a dict of port number that the kernel is listening on. It is set
52 # by record_ports and used by connect_request.
52 # by record_ports and used by connect_request.
53 _recorded_ports = Dict()
53 _recorded_ports = Dict()
54
54
55 #---------------------------------------------------------------------------
55 #---------------------------------------------------------------------------
56 # Kernel interface
56 # Kernel interface
57 #---------------------------------------------------------------------------
57 #---------------------------------------------------------------------------
58
58
59 session = Instance(Session)
59 session = Instance(Session)
60 shell_socket = Instance('zmq.Socket')
60 shell_socket = Instance('zmq.Socket')
61 iopub_socket = Instance('zmq.Socket')
61 iopub_socket = Instance('zmq.Socket')
62 stdin_socket = Instance('zmq.Socket')
62 stdin_socket = Instance('zmq.Socket')
63 log = Instance('logging.Logger')
63
64
64 def __init__(self, **kwargs):
65 def __init__(self, **kwargs):
65 super(Kernel, self).__init__(**kwargs)
66 super(Kernel, self).__init__(**kwargs)
66 self.user_ns = {}
67 self.user_ns = {}
67 self.history = []
68 self.history = []
68 self.compiler = CommandCompiler()
69 self.compiler = CommandCompiler()
69 self.completer = KernelCompleter(self.user_ns)
70 self.completer = KernelCompleter(self.user_ns)
70
71
71 # Build dict of handlers for message types
72 # Build dict of handlers for message types
72 msg_types = [ 'execute_request', 'complete_request',
73 msg_types = [ 'execute_request', 'complete_request',
73 'object_info_request', 'shutdown_request' ]
74 'object_info_request', 'shutdown_request' ]
74 self.handlers = {}
75 self.handlers = {}
75 for msg_type in msg_types:
76 for msg_type in msg_types:
76 self.handlers[msg_type] = getattr(self, msg_type)
77 self.handlers[msg_type] = getattr(self, msg_type)
77
78
78 def start(self):
79 def start(self):
79 """ Start the kernel main loop.
80 """ Start the kernel main loop.
80 """
81 """
81 while True:
82 while True:
82 ident,msg = self.session.recv(self.shell_socket,0)
83 ident,msg = self.session.recv(self.shell_socket,0)
83 assert ident is not None, "Missing message part."
84 assert ident is not None, "Missing message part."
84 omsg = Message(msg)
85 omsg = Message(msg)
85 print>>sys.__stdout__
86 self.log.debug(str(omsg))
86 print>>sys.__stdout__, omsg
87 handler = self.handlers.get(omsg.msg_type, None)
87 handler = self.handlers.get(omsg.msg_type, None)
88 if handler is None:
88 if handler is None:
89 print >> sys.__stderr__, "UNKNOWN MESSAGE TYPE:", omsg
89 self.log.error("UNKNOWN MESSAGE TYPE: %s"%omsg)
90 else:
90 else:
91 handler(ident, omsg)
91 handler(ident, omsg)
92
92
93 def record_ports(self, ports):
93 def record_ports(self, ports):
94 """Record the ports that this kernel is using.
94 """Record the ports that this kernel is using.
95
95
96 The creator of the Kernel instance must call this methods if they
96 The creator of the Kernel instance must call this methods if they
97 want the :meth:`connect_request` method to return the port numbers.
97 want the :meth:`connect_request` method to return the port numbers.
98 """
98 """
99 self._recorded_ports = ports
99 self._recorded_ports = ports
100
100
101 #---------------------------------------------------------------------------
101 #---------------------------------------------------------------------------
102 # Kernel request handlers
102 # Kernel request handlers
103 #---------------------------------------------------------------------------
103 #---------------------------------------------------------------------------
104
104
105 def execute_request(self, ident, parent):
105 def execute_request(self, ident, parent):
106 try:
106 try:
107 code = parent[u'content'][u'code']
107 code = parent[u'content'][u'code']
108 except:
108 except:
109 print>>sys.__stderr__, "Got bad msg: "
109 self.log.error("Got bad msg: %s"%Message(parent))
110 print>>sys.__stderr__, Message(parent)
111 return
110 return
112 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
111 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
113
112
114 try:
113 try:
115 comp_code = self.compiler(code, '<zmq-kernel>')
114 comp_code = self.compiler(code, '<zmq-kernel>')
116
115
117 # Replace raw_input. Note that is not sufficient to replace
116 # Replace raw_input. Note that is not sufficient to replace
118 # raw_input in the user namespace.
117 # raw_input in the user namespace.
119 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
118 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
120 __builtin__.raw_input = raw_input
119 __builtin__.raw_input = raw_input
121
120
122 # Set the parent message of the display hook and out streams.
121 # Set the parent message of the display hook and out streams.
123 sys.displayhook.set_parent(parent)
122 sys.displayhook.set_parent(parent)
124 sys.stdout.set_parent(parent)
123 sys.stdout.set_parent(parent)
125 sys.stderr.set_parent(parent)
124 sys.stderr.set_parent(parent)
126
125
127 exec comp_code in self.user_ns, self.user_ns
126 exec comp_code in self.user_ns, self.user_ns
128 except:
127 except:
129 etype, evalue, tb = sys.exc_info()
128 etype, evalue, tb = sys.exc_info()
130 tb = traceback.format_exception(etype, evalue, tb)
129 tb = traceback.format_exception(etype, evalue, tb)
131 exc_content = {
130 exc_content = {
132 u'status' : u'error',
131 u'status' : u'error',
133 u'traceback' : tb,
132 u'traceback' : tb,
134 u'ename' : unicode(etype.__name__),
133 u'ename' : unicode(etype.__name__),
135 u'evalue' : unicode(evalue)
134 u'evalue' : unicode(evalue)
136 }
135 }
137 exc_msg = self.session.send(self.iopub_socket, u'pyerr', exc_content, parent)
136 exc_msg = self.session.send(self.iopub_socket, u'pyerr', exc_content, parent)
138 reply_content = exc_content
137 reply_content = exc_content
139 else:
138 else:
140 reply_content = { 'status' : 'ok', 'payload' : {} }
139 reply_content = { 'status' : 'ok', 'payload' : {} }
141
140
142 # Flush output before sending the reply.
141 # Flush output before sending the reply.
143 sys.stderr.flush()
142 sys.stderr.flush()
144 sys.stdout.flush()
143 sys.stdout.flush()
145 # FIXME: on rare occasions, the flush doesn't seem to make it to the
144 # FIXME: on rare occasions, the flush doesn't seem to make it to the
146 # clients... This seems to mitigate the problem, but we definitely need
145 # clients... This seems to mitigate the problem, but we definitely need
147 # to better understand what's going on.
146 # to better understand what's going on.
148 if self._execute_sleep:
147 if self._execute_sleep:
149 time.sleep(self._execute_sleep)
148 time.sleep(self._execute_sleep)
150
149
151 # Send the reply.
150 # Send the reply.
152 reply_msg = self.session.send(self.shell_socket, u'execute_reply', reply_content, parent, ident=ident)
151 reply_msg = self.session.send(self.shell_socket, u'execute_reply', reply_content, parent, ident=ident)
153 print>>sys.__stdout__, Message(reply_msg)
152 self.log.debug(Message(reply_msg))
154 if reply_msg['content']['status'] == u'error':
153 if reply_msg['content']['status'] == u'error':
155 self._abort_queue()
154 self._abort_queue()
156
155
157 def complete_request(self, ident, parent):
156 def complete_request(self, ident, parent):
158 matches = {'matches' : self._complete(parent),
157 matches = {'matches' : self._complete(parent),
159 'status' : 'ok'}
158 'status' : 'ok'}
160 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
159 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
161 matches, parent, ident)
160 matches, parent, ident)
162 print >> sys.__stdout__, completion_msg
161 self.log.debug(completion_msg)
163
162
164 def object_info_request(self, ident, parent):
163 def object_info_request(self, ident, parent):
165 context = parent['content']['oname'].split('.')
164 context = parent['content']['oname'].split('.')
166 object_info = self._object_info(context)
165 object_info = self._object_info(context)
167 msg = self.session.send(self.shell_socket, 'object_info_reply',
166 msg = self.session.send(self.shell_socket, 'object_info_reply',
168 object_info, parent, ident)
167 object_info, parent, ident)
169 print >> sys.__stdout__, msg
168 self.log.debug(msg)
170
169
171 def shutdown_request(self, ident, parent):
170 def shutdown_request(self, ident, parent):
172 content = dict(parent['content'])
171 content = dict(parent['content'])
173 msg = self.session.send(self.shell_socket, 'shutdown_reply',
172 msg = self.session.send(self.shell_socket, 'shutdown_reply',
174 content, parent, ident)
173 content, parent, ident)
175 msg = self.session.send(self.iopub_socket, 'shutdown_reply',
174 msg = self.session.send(self.iopub_socket, 'shutdown_reply',
176 content, parent, ident)
175 content, parent, ident)
177 print >> sys.__stdout__, msg
176 self.log.debug(msg)
178 time.sleep(0.1)
177 time.sleep(0.1)
179 sys.exit(0)
178 sys.exit(0)
180
179
181 #---------------------------------------------------------------------------
180 #---------------------------------------------------------------------------
182 # Protected interface
181 # Protected interface
183 #---------------------------------------------------------------------------
182 #---------------------------------------------------------------------------
184
183
185 def _abort_queue(self):
184 def _abort_queue(self):
186 while True:
185 while True:
187 ident,msg = self.session.recv(self.reply_socket, zmq.NOBLOCK)
186 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
188 if msg is None:
187 if msg is None:
188 # msg=None on EAGAIN
189 break
189 break
190 else:
190 else:
191 assert ident is not None, "Unexpected missing message part."
191 assert ident is not None, "Missing message part."
192 print>>sys.__stdout__, "Aborting:"
192 self.log.debug("Aborting: %s"%Message(msg))
193 print>>sys.__stdout__, Message(msg)
194 msg_type = msg['msg_type']
193 msg_type = msg['msg_type']
195 reply_type = msg_type.split('_')[0] + '_reply'
194 reply_type = msg_type.split('_')[0] + '_reply'
196 reply_msg = self.session.send(self.shell_socket, reply_type, {'status':'aborted'}, msg, ident=ident)
195 reply_msg = self.session.send(self.shell_socket, reply_type, {'status':'aborted'}, msg, ident=ident)
197 print>>sys.__stdout__, Message(reply_msg)
196 self.log.debug(Message(reply_msg))
198 # We need to wait a bit for requests to come in. This can probably
197 # We need to wait a bit for requests to come in. This can probably
199 # be set shorter for true asynchronous clients.
198 # be set shorter for true asynchronous clients.
200 time.sleep(0.1)
199 time.sleep(0.1)
201
200
202 def _raw_input(self, prompt, ident, parent):
201 def _raw_input(self, prompt, ident, parent):
203 # Flush output before making the request.
202 # Flush output before making the request.
204 sys.stderr.flush()
203 sys.stderr.flush()
205 sys.stdout.flush()
204 sys.stdout.flush()
206
205
207 # Send the input request.
206 # Send the input request.
208 content = dict(prompt=prompt)
207 content = dict(prompt=prompt)
209 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
208 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
210
209
211 # Await a response.
210 # Await a response.
212 ident,reply = self.session.recv(self.stdin_socket, 0)
211 ident,reply = self.session.recv(self.stdin_socket, 0)
213 try:
212 try:
214 value = reply['content']['value']
213 value = reply['content']['value']
215 except:
214 except:
216 print>>sys.__stderr__, "Got bad raw_input reply: "
215 self.log.error("Got bad raw_input reply: %s"%Message(parent))
217 print>>sys.__stderr__, Message(parent)
218 value = ''
216 value = ''
219 return value
217 return value
220
218
221 def _complete(self, msg):
219 def _complete(self, msg):
222 return self.completer.complete(msg.content.line, msg.content.text)
220 return self.completer.complete(msg.content.line, msg.content.text)
223
221
224 def _object_info(self, context):
222 def _object_info(self, context):
225 symbol, leftover = self._symbol_from_context(context)
223 symbol, leftover = self._symbol_from_context(context)
226 if symbol is not None and not leftover:
224 if symbol is not None and not leftover:
227 doc = getattr(symbol, '__doc__', '')
225 doc = getattr(symbol, '__doc__', '')
228 else:
226 else:
229 doc = ''
227 doc = ''
230 object_info = dict(docstring = doc)
228 object_info = dict(docstring = doc)
231 return object_info
229 return object_info
232
230
233 def _symbol_from_context(self, context):
231 def _symbol_from_context(self, context):
234 if not context:
232 if not context:
235 return None, context
233 return None, context
236
234
237 base_symbol_string = context[0]
235 base_symbol_string = context[0]
238 symbol = self.user_ns.get(base_symbol_string, None)
236 symbol = self.user_ns.get(base_symbol_string, None)
239 if symbol is None:
237 if symbol is None:
240 symbol = __builtin__.__dict__.get(base_symbol_string, None)
238 symbol = __builtin__.__dict__.get(base_symbol_string, None)
241 if symbol is None:
239 if symbol is None:
242 return None, context
240 return None, context
243
241
244 context = context[1:]
242 context = context[1:]
245 for i, name in enumerate(context):
243 for i, name in enumerate(context):
246 new_symbol = getattr(symbol, name, None)
244 new_symbol = getattr(symbol, name, None)
247 if new_symbol is None:
245 if new_symbol is None:
248 return symbol, context[i:]
246 return symbol, context[i:]
249 else:
247 else:
250 symbol = new_symbol
248 symbol = new_symbol
251
249
252 return symbol, []
250 return symbol, []
253
251
254 #-----------------------------------------------------------------------------
252 #-----------------------------------------------------------------------------
255 # Kernel main and launch functions
253 # Kernel main and launch functions
256 #-----------------------------------------------------------------------------
254 #-----------------------------------------------------------------------------
257
255
258 def launch_kernel(*args, **kwargs):
256 def launch_kernel(*args, **kwargs):
259 """ Launches a simple Python kernel, binding to the specified ports.
257 """ Launches a simple Python kernel, binding to the specified ports.
260
258
261 This function simply calls entry_point.base_launch_kernel with the right first
259 This function simply calls entry_point.base_launch_kernel with the right first
262 command to start a pykernel. See base_launch_kernel for arguments.
260 command to start a pykernel. See base_launch_kernel for arguments.
263
261
264 Returns
262 Returns
265 -------
263 -------
266 A tuple of form:
264 A tuple of form:
267 (kernel_process, xrep_port, pub_port, req_port, hb_port)
265 (kernel_process, xrep_port, pub_port, req_port, hb_port)
268 where kernel_process is a Popen object and the ports are integers.
266 where kernel_process is a Popen object and the ports are integers.
269 """
267 """
270 return base_launch_kernel('from IPython.zmq.pykernel import main; main()',
268 return base_launch_kernel('from IPython.zmq.pykernel import main; main()',
271 *args, **kwargs)
269 *args, **kwargs)
272
270
273 def main():
271 def main():
274 """Run a PyKernel as an application"""
272 """Run a PyKernel as an application"""
275 app = KernelApp.instance()
273 app = KernelApp.instance()
276 app.initialize()
274 app.initialize()
277 app.start()
275 app.start()
278
276
279 if __name__ == '__main__':
277 if __name__ == '__main__':
280 main()
278 main()
General Comments 0
You need to be logged in to leave comments. Login now