##// END OF EJS Templates
use CFRunLoop directly in `ipython kernel --pylab osx`...
MinRK -
Show More
@@ -1,702 +1,769 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 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports.
18 # Standard library imports.
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25 # System library imports.
25 # System library imports.
26 import zmq
26 import zmq
27
27
28 # Local imports.
28 # Local imports.
29 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
30 from IPython.config.application import boolean_flag
30 from IPython.config.application import boolean_flag
31 from IPython.core.application import ProfileDir
31 from IPython.core.application import ProfileDir
32 from IPython.core.shellapp import (
32 from IPython.core.shellapp import (
33 InteractiveShellApp, shell_flags, shell_aliases
33 InteractiveShellApp, shell_flags, shell_aliases
34 )
34 )
35 from IPython.utils import io
35 from IPython.utils import io
36 from IPython.utils import py3compat
36 from IPython.utils import py3compat
37 from IPython.utils.jsonutil import json_clean
37 from IPython.utils.jsonutil import json_clean
38 from IPython.lib import pylabtools
38 from IPython.lib import pylabtools
39 from IPython.utils.traitlets import (
39 from IPython.utils.traitlets import (
40 List, Instance, Float, Dict, Bool, Int, Unicode, CaselessStrEnum
40 List, Instance, Float, Dict, Bool, Int, Unicode, CaselessStrEnum
41 )
41 )
42
42
43 from entry_point import base_launch_kernel
43 from entry_point import base_launch_kernel
44 from kernelapp import KernelApp, kernel_flags, kernel_aliases
44 from kernelapp import KernelApp, kernel_flags, kernel_aliases
45 from iostream import OutStream
45 from iostream import OutStream
46 from session import Session, Message
46 from session import Session, Message
47 from zmqshell import ZMQInteractiveShell
47 from zmqshell import ZMQInteractiveShell
48
48
49
49
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51 # Main kernel class
51 # Main kernel class
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53
53
54 class Kernel(Configurable):
54 class Kernel(Configurable):
55
55
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57 # Kernel interface
57 # Kernel interface
58 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
59
59
60 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
60 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
61 session = Instance(Session)
61 session = Instance(Session)
62 shell_socket = Instance('zmq.Socket')
62 shell_socket = Instance('zmq.Socket')
63 iopub_socket = Instance('zmq.Socket')
63 iopub_socket = Instance('zmq.Socket')
64 stdin_socket = Instance('zmq.Socket')
64 stdin_socket = Instance('zmq.Socket')
65 log = Instance(logging.Logger)
65 log = Instance(logging.Logger)
66
66
67 # Private interface
67 # Private interface
68
68
69 # Time to sleep after flushing the stdout/err buffers in each execute
69 # Time to sleep after flushing the stdout/err buffers in each execute
70 # cycle. While this introduces a hard limit on the minimal latency of the
70 # cycle. While this introduces a hard limit on the minimal latency of the
71 # execute cycle, it helps prevent output synchronization problems for
71 # execute cycle, it helps prevent output synchronization problems for
72 # clients.
72 # clients.
73 # Units are in seconds. The minimum zmq latency on local host is probably
73 # Units are in seconds. The minimum zmq latency on local host is probably
74 # ~150 microseconds, set this to 500us for now. We may need to increase it
74 # ~150 microseconds, set this to 500us for now. We may need to increase it
75 # a little if it's not enough after more interactive testing.
75 # a little if it's not enough after more interactive testing.
76 _execute_sleep = Float(0.0005, config=True)
76 _execute_sleep = Float(0.0005, config=True)
77
77
78 # Frequency of the kernel's event loop.
78 # Frequency of the kernel's event loop.
79 # Units are in seconds, kernel subclasses for GUI toolkits may need to
79 # Units are in seconds, kernel subclasses for GUI toolkits may need to
80 # adapt to milliseconds.
80 # adapt to milliseconds.
81 _poll_interval = Float(0.05, config=True)
81 _poll_interval = Float(0.05, config=True)
82
82
83 # If the shutdown was requested over the network, we leave here the
83 # If the shutdown was requested over the network, we leave here the
84 # necessary reply message so it can be sent by our registered atexit
84 # necessary reply message so it can be sent by our registered atexit
85 # handler. This ensures that the reply is only sent to clients truly at
85 # handler. This ensures that the reply is only sent to clients truly at
86 # the end of our shutdown process (which happens after the underlying
86 # the end of our shutdown process (which happens after the underlying
87 # IPython shell's own shutdown).
87 # IPython shell's own shutdown).
88 _shutdown_message = None
88 _shutdown_message = None
89
89
90 # This is a dict of port number that the kernel is listening on. It is set
90 # This is a dict of port number that the kernel is listening on. It is set
91 # by record_ports and used by connect_request.
91 # by record_ports and used by connect_request.
92 _recorded_ports = Dict()
92 _recorded_ports = Dict()
93
93
94
94
95
95
96 def __init__(self, **kwargs):
96 def __init__(self, **kwargs):
97 super(Kernel, self).__init__(**kwargs)
97 super(Kernel, self).__init__(**kwargs)
98
98
99 # Before we even start up the shell, register *first* our exit handlers
99 # Before we even start up the shell, register *first* our exit handlers
100 # so they come before the shell's
100 # so they come before the shell's
101 atexit.register(self._at_shutdown)
101 atexit.register(self._at_shutdown)
102
102
103 # Initialize the InteractiveShell subclass
103 # Initialize the InteractiveShell subclass
104 self.shell = ZMQInteractiveShell.instance(config=self.config)
104 self.shell = ZMQInteractiveShell.instance(config=self.config)
105 self.shell.displayhook.session = self.session
105 self.shell.displayhook.session = self.session
106 self.shell.displayhook.pub_socket = self.iopub_socket
106 self.shell.displayhook.pub_socket = self.iopub_socket
107 self.shell.display_pub.session = self.session
107 self.shell.display_pub.session = self.session
108 self.shell.display_pub.pub_socket = self.iopub_socket
108 self.shell.display_pub.pub_socket = self.iopub_socket
109
109
110 # TMP - hack while developing
110 # TMP - hack while developing
111 self.shell._reply_content = None
111 self.shell._reply_content = None
112
112
113 # Build dict of handlers for message types
113 # Build dict of handlers for message types
114 msg_types = [ 'execute_request', 'complete_request',
114 msg_types = [ 'execute_request', 'complete_request',
115 'object_info_request', 'history_request',
115 'object_info_request', 'history_request',
116 'connect_request', 'shutdown_request']
116 'connect_request', 'shutdown_request']
117 self.handlers = {}
117 self.handlers = {}
118 for msg_type in msg_types:
118 for msg_type in msg_types:
119 self.handlers[msg_type] = getattr(self, msg_type)
119 self.handlers[msg_type] = getattr(self, msg_type)
120
120
121 def do_one_iteration(self):
121 def do_one_iteration(self):
122 """Do one iteration of the kernel's evaluation loop.
122 """Do one iteration of the kernel's evaluation loop.
123 """
123 """
124 try:
124 try:
125 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
125 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
126 except Exception:
126 except Exception:
127 self.log.warn("Invalid Message:", exc_info=True)
127 self.log.warn("Invalid Message:", exc_info=True)
128 return
128 return
129 if msg is None:
129 if msg is None:
130 return
130 return
131
131
132 msg_type = msg['header']['msg_type']
132 msg_type = msg['header']['msg_type']
133
133
134 # This assert will raise in versions of zeromq 2.0.7 and lesser.
134 # This assert will raise in versions of zeromq 2.0.7 and lesser.
135 # We now require 2.0.8 or above, so we can uncomment for safety.
135 # We now require 2.0.8 or above, so we can uncomment for safety.
136 # print(ident,msg, file=sys.__stdout__)
136 # print(ident,msg, file=sys.__stdout__)
137 assert ident is not None, "Missing message part."
137 assert ident is not None, "Missing message part."
138
138
139 # Print some info about this message and leave a '--->' marker, so it's
139 # Print some info about this message and leave a '--->' marker, so it's
140 # easier to trace visually the message chain when debugging. Each
140 # easier to trace visually the message chain when debugging. Each
141 # handler prints its message at the end.
141 # handler prints its message at the end.
142 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
142 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
143 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
143 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
144
144
145 # Find and call actual handler for message
145 # Find and call actual handler for message
146 handler = self.handlers.get(msg_type, None)
146 handler = self.handlers.get(msg_type, None)
147 if handler is None:
147 if handler is None:
148 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
148 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
149 else:
149 else:
150 handler(ident, msg)
150 handler(ident, msg)
151
151
152 # Check whether we should exit, in case the incoming message set the
152 # Check whether we should exit, in case the incoming message set the
153 # exit flag on
153 # exit flag on
154 if self.shell.exit_now:
154 if self.shell.exit_now:
155 self.log.debug('\nExiting IPython kernel...')
155 self.log.debug('\nExiting IPython kernel...')
156 # We do a normal, clean exit, which allows any actions registered
156 # We do a normal, clean exit, which allows any actions registered
157 # via atexit (such as history saving) to take place.
157 # via atexit (such as history saving) to take place.
158 sys.exit(0)
158 sys.exit(0)
159
159
160
160
161 def start(self):
161 def start(self):
162 """ Start the kernel main loop.
162 """ Start the kernel main loop.
163 """
163 """
164 poller = zmq.Poller()
164 poller = zmq.Poller()
165 poller.register(self.shell_socket, zmq.POLLIN)
165 poller.register(self.shell_socket, zmq.POLLIN)
166 while True:
166 while True:
167 try:
167 try:
168 # scale by extra factor of 10, because there is no
168 # scale by extra factor of 10, because there is no
169 # reason for this to be anything less than ~ 0.1s
169 # reason for this to be anything less than ~ 0.1s
170 # since it is a real poller and will respond
170 # since it is a real poller and will respond
171 # to events immediately
171 # to events immediately
172
172
173 # double nested try/except, to properly catch KeyboardInterrupt
173 # double nested try/except, to properly catch KeyboardInterrupt
174 # due to pyzmq Issue #130
174 # due to pyzmq Issue #130
175 try:
175 try:
176 poller.poll(10*1000*self._poll_interval)
176 poller.poll(10*1000*self._poll_interval)
177 self.do_one_iteration()
177 self.do_one_iteration()
178 except:
178 except:
179 raise
179 raise
180 except KeyboardInterrupt:
180 except KeyboardInterrupt:
181 # Ctrl-C shouldn't crash the kernel
181 # Ctrl-C shouldn't crash the kernel
182 io.raw_print("KeyboardInterrupt caught in kernel")
182 io.raw_print("KeyboardInterrupt caught in kernel")
183
183
184 def record_ports(self, ports):
184 def record_ports(self, ports):
185 """Record the ports that this kernel is using.
185 """Record the ports that this kernel is using.
186
186
187 The creator of the Kernel instance must call this methods if they
187 The creator of the Kernel instance must call this methods if they
188 want the :meth:`connect_request` method to return the port numbers.
188 want the :meth:`connect_request` method to return the port numbers.
189 """
189 """
190 self._recorded_ports = ports
190 self._recorded_ports = ports
191
191
192 #---------------------------------------------------------------------------
192 #---------------------------------------------------------------------------
193 # Kernel request handlers
193 # Kernel request handlers
194 #---------------------------------------------------------------------------
194 #---------------------------------------------------------------------------
195
195
196 def _publish_pyin(self, code, parent):
196 def _publish_pyin(self, code, parent):
197 """Publish the code request on the pyin stream."""
197 """Publish the code request on the pyin stream."""
198
198
199 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
199 pyin_msg = self.session.send(self.iopub_socket, u'pyin',{u'code':code}, parent=parent)
200
200
201 def execute_request(self, ident, parent):
201 def execute_request(self, ident, parent):
202
202
203 status_msg = self.session.send(self.iopub_socket,
203 status_msg = self.session.send(self.iopub_socket,
204 u'status',
204 u'status',
205 {u'execution_state':u'busy'},
205 {u'execution_state':u'busy'},
206 parent=parent
206 parent=parent
207 )
207 )
208
208
209 try:
209 try:
210 content = parent[u'content']
210 content = parent[u'content']
211 code = content[u'code']
211 code = content[u'code']
212 silent = content[u'silent']
212 silent = content[u'silent']
213 except:
213 except:
214 self.log.error("Got bad msg: ")
214 self.log.error("Got bad msg: ")
215 self.log.error(str(Message(parent)))
215 self.log.error(str(Message(parent)))
216 return
216 return
217
217
218 shell = self.shell # we'll need this a lot here
218 shell = self.shell # we'll need this a lot here
219
219
220 # Replace raw_input. Note that is not sufficient to replace
220 # Replace raw_input. Note that is not sufficient to replace
221 # raw_input in the user namespace.
221 # raw_input in the user namespace.
222 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
222 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
223 if py3compat.PY3:
223 if py3compat.PY3:
224 __builtin__.input = raw_input
224 __builtin__.input = raw_input
225 else:
225 else:
226 __builtin__.raw_input = raw_input
226 __builtin__.raw_input = raw_input
227
227
228 # Set the parent message of the display hook and out streams.
228 # Set the parent message of the display hook and out streams.
229 shell.displayhook.set_parent(parent)
229 shell.displayhook.set_parent(parent)
230 shell.display_pub.set_parent(parent)
230 shell.display_pub.set_parent(parent)
231 sys.stdout.set_parent(parent)
231 sys.stdout.set_parent(parent)
232 sys.stderr.set_parent(parent)
232 sys.stderr.set_parent(parent)
233
233
234 # Re-broadcast our input for the benefit of listening clients, and
234 # Re-broadcast our input for the benefit of listening clients, and
235 # start computing output
235 # start computing output
236 if not silent:
236 if not silent:
237 self._publish_pyin(code, parent)
237 self._publish_pyin(code, parent)
238
238
239 reply_content = {}
239 reply_content = {}
240 try:
240 try:
241 if silent:
241 if silent:
242 # run_code uses 'exec' mode, so no displayhook will fire, and it
242 # run_code uses 'exec' mode, so no displayhook will fire, and it
243 # doesn't call logging or history manipulations. Print
243 # doesn't call logging or history manipulations. Print
244 # statements in that code will obviously still execute.
244 # statements in that code will obviously still execute.
245 shell.run_code(code)
245 shell.run_code(code)
246 else:
246 else:
247 # FIXME: the shell calls the exception handler itself.
247 # FIXME: the shell calls the exception handler itself.
248 shell.run_cell(code)
248 shell.run_cell(code)
249 except:
249 except:
250 status = u'error'
250 status = u'error'
251 # FIXME: this code right now isn't being used yet by default,
251 # FIXME: this code right now isn't being used yet by default,
252 # because the run_cell() call above directly fires off exception
252 # because the run_cell() call above directly fires off exception
253 # reporting. This code, therefore, is only active in the scenario
253 # reporting. This code, therefore, is only active in the scenario
254 # where runlines itself has an unhandled exception. We need to
254 # where runlines itself has an unhandled exception. We need to
255 # uniformize this, for all exception construction to come from a
255 # uniformize this, for all exception construction to come from a
256 # single location in the codbase.
256 # single location in the codbase.
257 etype, evalue, tb = sys.exc_info()
257 etype, evalue, tb = sys.exc_info()
258 tb_list = traceback.format_exception(etype, evalue, tb)
258 tb_list = traceback.format_exception(etype, evalue, tb)
259 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
259 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
260 else:
260 else:
261 status = u'ok'
261 status = u'ok'
262
262
263 reply_content[u'status'] = status
263 reply_content[u'status'] = status
264
264
265 # Return the execution counter so clients can display prompts
265 # Return the execution counter so clients can display prompts
266 reply_content['execution_count'] = shell.execution_count -1
266 reply_content['execution_count'] = shell.execution_count -1
267
267
268 # FIXME - fish exception info out of shell, possibly left there by
268 # FIXME - fish exception info out of shell, possibly left there by
269 # runlines. We'll need to clean up this logic later.
269 # runlines. We'll need to clean up this logic later.
270 if shell._reply_content is not None:
270 if shell._reply_content is not None:
271 reply_content.update(shell._reply_content)
271 reply_content.update(shell._reply_content)
272 # reset after use
272 # reset after use
273 shell._reply_content = None
273 shell._reply_content = None
274
274
275 # At this point, we can tell whether the main code execution succeeded
275 # At this point, we can tell whether the main code execution succeeded
276 # or not. If it did, we proceed to evaluate user_variables/expressions
276 # or not. If it did, we proceed to evaluate user_variables/expressions
277 if reply_content['status'] == 'ok':
277 if reply_content['status'] == 'ok':
278 reply_content[u'user_variables'] = \
278 reply_content[u'user_variables'] = \
279 shell.user_variables(content[u'user_variables'])
279 shell.user_variables(content[u'user_variables'])
280 reply_content[u'user_expressions'] = \
280 reply_content[u'user_expressions'] = \
281 shell.user_expressions(content[u'user_expressions'])
281 shell.user_expressions(content[u'user_expressions'])
282 else:
282 else:
283 # If there was an error, don't even try to compute variables or
283 # If there was an error, don't even try to compute variables or
284 # expressions
284 # expressions
285 reply_content[u'user_variables'] = {}
285 reply_content[u'user_variables'] = {}
286 reply_content[u'user_expressions'] = {}
286 reply_content[u'user_expressions'] = {}
287
287
288 # Payloads should be retrieved regardless of outcome, so we can both
288 # Payloads should be retrieved regardless of outcome, so we can both
289 # recover partial output (that could have been generated early in a
289 # recover partial output (that could have been generated early in a
290 # block, before an error) and clear the payload system always.
290 # block, before an error) and clear the payload system always.
291 reply_content[u'payload'] = shell.payload_manager.read_payload()
291 reply_content[u'payload'] = shell.payload_manager.read_payload()
292 # Be agressive about clearing the payload because we don't want
292 # Be agressive about clearing the payload because we don't want
293 # it to sit in memory until the next execute_request comes in.
293 # it to sit in memory until the next execute_request comes in.
294 shell.payload_manager.clear_payload()
294 shell.payload_manager.clear_payload()
295
295
296 # Flush output before sending the reply.
296 # Flush output before sending the reply.
297 sys.stdout.flush()
297 sys.stdout.flush()
298 sys.stderr.flush()
298 sys.stderr.flush()
299 # FIXME: on rare occasions, the flush doesn't seem to make it to the
299 # FIXME: on rare occasions, the flush doesn't seem to make it to the
300 # clients... This seems to mitigate the problem, but we definitely need
300 # clients... This seems to mitigate the problem, but we definitely need
301 # to better understand what's going on.
301 # to better understand what's going on.
302 if self._execute_sleep:
302 if self._execute_sleep:
303 time.sleep(self._execute_sleep)
303 time.sleep(self._execute_sleep)
304
304
305 # Send the reply.
305 # Send the reply.
306 reply_content = json_clean(reply_content)
306 reply_content = json_clean(reply_content)
307 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
307 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
308 reply_content, parent, ident=ident)
308 reply_content, parent, ident=ident)
309 self.log.debug(str(reply_msg))
309 self.log.debug(str(reply_msg))
310
310
311 if reply_msg['content']['status'] == u'error':
311 if reply_msg['content']['status'] == u'error':
312 self._abort_queue()
312 self._abort_queue()
313
313
314 status_msg = self.session.send(self.iopub_socket,
314 status_msg = self.session.send(self.iopub_socket,
315 u'status',
315 u'status',
316 {u'execution_state':u'idle'},
316 {u'execution_state':u'idle'},
317 parent=parent
317 parent=parent
318 )
318 )
319
319
320 def complete_request(self, ident, parent):
320 def complete_request(self, ident, parent):
321 txt, matches = self._complete(parent)
321 txt, matches = self._complete(parent)
322 matches = {'matches' : matches,
322 matches = {'matches' : matches,
323 'matched_text' : txt,
323 'matched_text' : txt,
324 'status' : 'ok'}
324 'status' : 'ok'}
325 matches = json_clean(matches)
325 matches = json_clean(matches)
326 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
326 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
327 matches, parent, ident)
327 matches, parent, ident)
328 self.log.debug(str(completion_msg))
328 self.log.debug(str(completion_msg))
329
329
330 def object_info_request(self, ident, parent):
330 def object_info_request(self, ident, parent):
331 object_info = self.shell.object_inspect(parent['content']['oname'])
331 object_info = self.shell.object_inspect(parent['content']['oname'])
332 # Before we send this object over, we scrub it for JSON usage
332 # Before we send this object over, we scrub it for JSON usage
333 oinfo = json_clean(object_info)
333 oinfo = json_clean(object_info)
334 msg = self.session.send(self.shell_socket, 'object_info_reply',
334 msg = self.session.send(self.shell_socket, 'object_info_reply',
335 oinfo, parent, ident)
335 oinfo, parent, ident)
336 self.log.debug(msg)
336 self.log.debug(msg)
337
337
338 def history_request(self, ident, parent):
338 def history_request(self, ident, parent):
339 # We need to pull these out, as passing **kwargs doesn't work with
339 # We need to pull these out, as passing **kwargs doesn't work with
340 # unicode keys before Python 2.6.5.
340 # unicode keys before Python 2.6.5.
341 hist_access_type = parent['content']['hist_access_type']
341 hist_access_type = parent['content']['hist_access_type']
342 raw = parent['content']['raw']
342 raw = parent['content']['raw']
343 output = parent['content']['output']
343 output = parent['content']['output']
344 if hist_access_type == 'tail':
344 if hist_access_type == 'tail':
345 n = parent['content']['n']
345 n = parent['content']['n']
346 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
346 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
347 include_latest=True)
347 include_latest=True)
348
348
349 elif hist_access_type == 'range':
349 elif hist_access_type == 'range':
350 session = parent['content']['session']
350 session = parent['content']['session']
351 start = parent['content']['start']
351 start = parent['content']['start']
352 stop = parent['content']['stop']
352 stop = parent['content']['stop']
353 hist = self.shell.history_manager.get_range(session, start, stop,
353 hist = self.shell.history_manager.get_range(session, start, stop,
354 raw=raw, output=output)
354 raw=raw, output=output)
355
355
356 elif hist_access_type == 'search':
356 elif hist_access_type == 'search':
357 pattern = parent['content']['pattern']
357 pattern = parent['content']['pattern']
358 hist = self.shell.history_manager.search(pattern, raw=raw, output=output)
358 hist = self.shell.history_manager.search(pattern, raw=raw, output=output)
359
359
360 else:
360 else:
361 hist = []
361 hist = []
362 content = {'history' : list(hist)}
362 content = {'history' : list(hist)}
363 content = json_clean(content)
363 content = json_clean(content)
364 msg = self.session.send(self.shell_socket, 'history_reply',
364 msg = self.session.send(self.shell_socket, 'history_reply',
365 content, parent, ident)
365 content, parent, ident)
366 self.log.debug(str(msg))
366 self.log.debug(str(msg))
367
367
368 def connect_request(self, ident, parent):
368 def connect_request(self, ident, parent):
369 if self._recorded_ports is not None:
369 if self._recorded_ports is not None:
370 content = self._recorded_ports.copy()
370 content = self._recorded_ports.copy()
371 else:
371 else:
372 content = {}
372 content = {}
373 msg = self.session.send(self.shell_socket, 'connect_reply',
373 msg = self.session.send(self.shell_socket, 'connect_reply',
374 content, parent, ident)
374 content, parent, ident)
375 self.log.debug(msg)
375 self.log.debug(msg)
376
376
377 def shutdown_request(self, ident, parent):
377 def shutdown_request(self, ident, parent):
378 self.shell.exit_now = True
378 self.shell.exit_now = True
379 self._shutdown_message = self.session.msg(u'shutdown_reply', parent['content'], parent)
379 self._shutdown_message = self.session.msg(u'shutdown_reply', parent['content'], parent)
380 sys.exit(0)
380 sys.exit(0)
381
381
382 #---------------------------------------------------------------------------
382 #---------------------------------------------------------------------------
383 # Protected interface
383 # Protected interface
384 #---------------------------------------------------------------------------
384 #---------------------------------------------------------------------------
385
385
386 def _abort_queue(self):
386 def _abort_queue(self):
387 while True:
387 while True:
388 try:
388 try:
389 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
389 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
390 except Exception:
390 except Exception:
391 self.log.warn("Invalid Message:", exc_info=True)
391 self.log.warn("Invalid Message:", exc_info=True)
392 continue
392 continue
393 if msg is None:
393 if msg is None:
394 break
394 break
395 else:
395 else:
396 assert ident is not None, \
396 assert ident is not None, \
397 "Unexpected missing message part."
397 "Unexpected missing message part."
398
398
399 self.log.debug("Aborting:\n"+str(Message(msg)))
399 self.log.debug("Aborting:\n"+str(Message(msg)))
400 msg_type = msg['header']['msg_type']
400 msg_type = msg['header']['msg_type']
401 reply_type = msg_type.split('_')[0] + '_reply'
401 reply_type = msg_type.split('_')[0] + '_reply'
402 reply_msg = self.session.send(self.shell_socket, reply_type,
402 reply_msg = self.session.send(self.shell_socket, reply_type,
403 {'status' : 'aborted'}, msg, ident=ident)
403 {'status' : 'aborted'}, msg, ident=ident)
404 self.log.debug(reply_msg)
404 self.log.debug(reply_msg)
405 # We need to wait a bit for requests to come in. This can probably
405 # We need to wait a bit for requests to come in. This can probably
406 # be set shorter for true asynchronous clients.
406 # be set shorter for true asynchronous clients.
407 time.sleep(0.1)
407 time.sleep(0.1)
408
408
409 def _raw_input(self, prompt, ident, parent):
409 def _raw_input(self, prompt, ident, parent):
410 # Flush output before making the request.
410 # Flush output before making the request.
411 sys.stderr.flush()
411 sys.stderr.flush()
412 sys.stdout.flush()
412 sys.stdout.flush()
413
413
414 # Send the input request.
414 # Send the input request.
415 content = json_clean(dict(prompt=prompt))
415 content = json_clean(dict(prompt=prompt))
416 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
416 msg = self.session.send(self.stdin_socket, u'input_request', content, parent)
417
417
418 # Await a response.
418 # Await a response.
419 while True:
419 while True:
420 try:
420 try:
421 ident, reply = self.session.recv(self.stdin_socket, 0)
421 ident, reply = self.session.recv(self.stdin_socket, 0)
422 except Exception:
422 except Exception:
423 self.log.warn("Invalid Message:", exc_info=True)
423 self.log.warn("Invalid Message:", exc_info=True)
424 else:
424 else:
425 break
425 break
426 try:
426 try:
427 value = reply['content']['value']
427 value = reply['content']['value']
428 except:
428 except:
429 self.log.error("Got bad raw_input reply: ")
429 self.log.error("Got bad raw_input reply: ")
430 self.log.error(str(Message(parent)))
430 self.log.error(str(Message(parent)))
431 value = ''
431 value = ''
432 return value
432 return value
433
433
434 def _complete(self, msg):
434 def _complete(self, msg):
435 c = msg['content']
435 c = msg['content']
436 try:
436 try:
437 cpos = int(c['cursor_pos'])
437 cpos = int(c['cursor_pos'])
438 except:
438 except:
439 # If we don't get something that we can convert to an integer, at
439 # If we don't get something that we can convert to an integer, at
440 # least attempt the completion guessing the cursor is at the end of
440 # least attempt the completion guessing the cursor is at the end of
441 # the text, if there's any, and otherwise of the line
441 # the text, if there's any, and otherwise of the line
442 cpos = len(c['text'])
442 cpos = len(c['text'])
443 if cpos==0:
443 if cpos==0:
444 cpos = len(c['line'])
444 cpos = len(c['line'])
445 return self.shell.complete(c['text'], c['line'], cpos)
445 return self.shell.complete(c['text'], c['line'], cpos)
446
446
447 def _object_info(self, context):
447 def _object_info(self, context):
448 symbol, leftover = self._symbol_from_context(context)
448 symbol, leftover = self._symbol_from_context(context)
449 if symbol is not None and not leftover:
449 if symbol is not None and not leftover:
450 doc = getattr(symbol, '__doc__', '')
450 doc = getattr(symbol, '__doc__', '')
451 else:
451 else:
452 doc = ''
452 doc = ''
453 object_info = dict(docstring = doc)
453 object_info = dict(docstring = doc)
454 return object_info
454 return object_info
455
455
456 def _symbol_from_context(self, context):
456 def _symbol_from_context(self, context):
457 if not context:
457 if not context:
458 return None, context
458 return None, context
459
459
460 base_symbol_string = context[0]
460 base_symbol_string = context[0]
461 symbol = self.shell.user_ns.get(base_symbol_string, None)
461 symbol = self.shell.user_ns.get(base_symbol_string, None)
462 if symbol is None:
462 if symbol is None:
463 symbol = __builtin__.__dict__.get(base_symbol_string, None)
463 symbol = __builtin__.__dict__.get(base_symbol_string, None)
464 if symbol is None:
464 if symbol is None:
465 return None, context
465 return None, context
466
466
467 context = context[1:]
467 context = context[1:]
468 for i, name in enumerate(context):
468 for i, name in enumerate(context):
469 new_symbol = getattr(symbol, name, None)
469 new_symbol = getattr(symbol, name, None)
470 if new_symbol is None:
470 if new_symbol is None:
471 return symbol, context[i:]
471 return symbol, context[i:]
472 else:
472 else:
473 symbol = new_symbol
473 symbol = new_symbol
474
474
475 return symbol, []
475 return symbol, []
476
476
477 def _at_shutdown(self):
477 def _at_shutdown(self):
478 """Actions taken at shutdown by the kernel, called by python's atexit.
478 """Actions taken at shutdown by the kernel, called by python's atexit.
479 """
479 """
480 # io.rprint("Kernel at_shutdown") # dbg
480 # io.rprint("Kernel at_shutdown") # dbg
481 if self._shutdown_message is not None:
481 if self._shutdown_message is not None:
482 self.session.send(self.shell_socket, self._shutdown_message)
482 self.session.send(self.shell_socket, self._shutdown_message)
483 self.session.send(self.iopub_socket, self._shutdown_message)
483 self.session.send(self.iopub_socket, self._shutdown_message)
484 self.log.debug(str(self._shutdown_message))
484 self.log.debug(str(self._shutdown_message))
485 # A very short sleep to give zmq time to flush its message buffers
485 # A very short sleep to give zmq time to flush its message buffers
486 # before Python truly shuts down.
486 # before Python truly shuts down.
487 time.sleep(0.01)
487 time.sleep(0.01)
488
488
489
489
490 class QtKernel(Kernel):
490 class QtKernel(Kernel):
491 """A Kernel subclass with Qt support."""
491 """A Kernel subclass with Qt support."""
492
492
493 def start(self):
493 def start(self):
494 """Start a kernel with QtPy4 event loop integration."""
494 """Start a kernel with QtPy4 event loop integration."""
495
495
496 from IPython.external.qt_for_kernel import QtCore
496 from IPython.external.qt_for_kernel import QtCore
497 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
497 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
498
498
499 self.app = get_app_qt4([" "])
499 self.app = get_app_qt4([" "])
500 self.app.setQuitOnLastWindowClosed(False)
500 self.app.setQuitOnLastWindowClosed(False)
501 self.timer = QtCore.QTimer()
501 self.timer = QtCore.QTimer()
502 self.timer.timeout.connect(self.do_one_iteration)
502 self.timer.timeout.connect(self.do_one_iteration)
503 # Units for the timer are in milliseconds
503 # Units for the timer are in milliseconds
504 self.timer.start(1000*self._poll_interval)
504 self.timer.start(1000*self._poll_interval)
505 start_event_loop_qt4(self.app)
505 start_event_loop_qt4(self.app)
506
506
507
507
508 class WxKernel(Kernel):
508 class WxKernel(Kernel):
509 """A Kernel subclass with Wx support."""
509 """A Kernel subclass with Wx support."""
510
510
511 def start(self):
511 def start(self):
512 """Start a kernel with wx event loop support."""
512 """Start a kernel with wx event loop support."""
513
513
514 import wx
514 import wx
515 from IPython.lib.guisupport import start_event_loop_wx
515 from IPython.lib.guisupport import start_event_loop_wx
516
516
517 doi = self.do_one_iteration
517 doi = self.do_one_iteration
518 # Wx uses milliseconds
518 # Wx uses milliseconds
519 poll_interval = int(1000*self._poll_interval)
519 poll_interval = int(1000*self._poll_interval)
520
520
521 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
521 # We have to put the wx.Timer in a wx.Frame for it to fire properly.
522 # We make the Frame hidden when we create it in the main app below.
522 # We make the Frame hidden when we create it in the main app below.
523 class TimerFrame(wx.Frame):
523 class TimerFrame(wx.Frame):
524 def __init__(self, func):
524 def __init__(self, func):
525 wx.Frame.__init__(self, None, -1)
525 wx.Frame.__init__(self, None, -1)
526 self.timer = wx.Timer(self)
526 self.timer = wx.Timer(self)
527 # Units for the timer are in milliseconds
527 # Units for the timer are in milliseconds
528 self.timer.Start(poll_interval)
528 self.timer.Start(poll_interval)
529 self.Bind(wx.EVT_TIMER, self.on_timer)
529 self.Bind(wx.EVT_TIMER, self.on_timer)
530 self.func = func
530 self.func = func
531
531
532 def on_timer(self, event):
532 def on_timer(self, event):
533 self.func()
533 self.func()
534
534
535 # We need a custom wx.App to create our Frame subclass that has the
535 # We need a custom wx.App to create our Frame subclass that has the
536 # wx.Timer to drive the ZMQ event loop.
536 # wx.Timer to drive the ZMQ event loop.
537 class IPWxApp(wx.App):
537 class IPWxApp(wx.App):
538 def OnInit(self):
538 def OnInit(self):
539 self.frame = TimerFrame(doi)
539 self.frame = TimerFrame(doi)
540 self.frame.Show(False)
540 self.frame.Show(False)
541 return True
541 return True
542
542
543 # The redirect=False here makes sure that wx doesn't replace
543 # The redirect=False here makes sure that wx doesn't replace
544 # sys.stdout/stderr with its own classes.
544 # sys.stdout/stderr with its own classes.
545 self.app = IPWxApp(redirect=False)
545 self.app = IPWxApp(redirect=False)
546 start_event_loop_wx(self.app)
546 start_event_loop_wx(self.app)
547
547
548
548
549 class TkKernel(Kernel):
549 class TkKernel(Kernel):
550 """A Kernel subclass with Tk support."""
550 """A Kernel subclass with Tk support."""
551
551
552 def start(self):
552 def start(self):
553 """Start a Tk enabled event loop."""
553 """Start a Tk enabled event loop."""
554
554
555 import Tkinter
555 import Tkinter
556 doi = self.do_one_iteration
556 doi = self.do_one_iteration
557 # Tk uses milliseconds
557 # Tk uses milliseconds
558 poll_interval = int(1000*self._poll_interval)
558 poll_interval = int(1000*self._poll_interval)
559 # For Tkinter, we create a Tk object and call its withdraw method.
559 # For Tkinter, we create a Tk object and call its withdraw method.
560 class Timer(object):
560 class Timer(object):
561 def __init__(self, func):
561 def __init__(self, func):
562 self.app = Tkinter.Tk()
562 self.app = Tkinter.Tk()
563 self.app.withdraw()
563 self.app.withdraw()
564 self.func = func
564 self.func = func
565
565
566 def on_timer(self):
566 def on_timer(self):
567 self.func()
567 self.func()
568 self.app.after(poll_interval, self.on_timer)
568 self.app.after(poll_interval, self.on_timer)
569
569
570 def start(self):
570 def start(self):
571 self.on_timer() # Call it once to get things going.
571 self.on_timer() # Call it once to get things going.
572 self.app.mainloop()
572 self.app.mainloop()
573
573
574 self.timer = Timer(doi)
574 self.timer = Timer(doi)
575 self.timer.start()
575 self.timer.start()
576
576
577
577
578 class GTKKernel(Kernel):
578 class GTKKernel(Kernel):
579 """A Kernel subclass with GTK support."""
579 """A Kernel subclass with GTK support."""
580
580
581 def start(self):
581 def start(self):
582 """Start the kernel, coordinating with the GTK event loop"""
582 """Start the kernel, coordinating with the GTK event loop"""
583 from .gui.gtkembed import GTKEmbed
583 from .gui.gtkembed import GTKEmbed
584
584
585 gtk_kernel = GTKEmbed(self)
585 gtk_kernel = GTKEmbed(self)
586 gtk_kernel.start()
586 gtk_kernel.start()
587
587
588
588
589 class OSXKernel(TkKernel):
590 """A Kernel subclass with Cocoa support via the matplotlib OSX backend."""
591
592 def start(self):
593 """Start the kernel, coordinating with the Cocoa CFRunLoop event loop
594 via the matplotlib MacOSX backend.
595 """
596 import matplotlib
597 if matplotlib.__version__ < '1.1.0':
598 self.log.warn(
599 "MacOSX backend in matplotlib %s doesn't have a Timer, "
600 "falling back on Tk for CFRunLoop integration. Note that "
601 "even this won't work if Tk is linked against X11 instead of "
602 "Cocoa (e.g. EPD). To use the MacOSX backend in the kernel, "
603 "you must use matplotlib >= 1.1.0, or a native libtk."
604 )
605 return TkKernel.start(self)
606
607 from matplotlib.backends.backend_macosx import TimerMac, show
608
609 # scale interval for sec->ms
610 poll_interval = int(1000*self._poll_interval)
611
612 real_excepthook = sys.excepthook
613 def handle_int(etype, value, tb):
614 """don't let KeyboardInterrupts look like crashes"""
615 if etype is KeyboardInterrupt:
616 io.raw_print("KeyboardInterrupt caught in CFRunLoop")
617 else:
618 real_excepthook(etype, value, tb)
619
620 # add doi() as a Timer to the CFRunLoop
621 def doi():
622 # restore excepthook during IPython code
623 sys.excepthook = real_excepthook
624 self.do_one_iteration()
625 # and back:
626 sys.excepthook = handle_int
627 t = TimerMac(poll_interval)
628 t.add_callback(doi)
629 t.start()
630
631 # but still need a Poller for when there are no active windows,
632 # during which time mainloop() returns immediately
633 poller = zmq.Poller()
634 poller.register(self.shell_socket, zmq.POLLIN)
635
636 while True:
637 try:
638 # double nested try/except, to properly catch KeyboardInterrupt
639 # due to pyzmq Issue #130
640 try:
641 # don't let interrupts during mainloop invoke crash_handler:
642 sys.excepthook = handle_int
643 show.mainloop()
644 sys.excepthook = real_excepthook
645 # use poller if mainloop returned (no windows)
646 # scale by extra factor of 10, since it's a real poll
647 poller.poll(10*poll_interval)
648 self.do_one_iteration()
649 except:
650 raise
651 except KeyboardInterrupt:
652 # Ctrl-C shouldn't crash the kernel
653 io.raw_print("KeyboardInterrupt caught in kernel")
654
655
589 #-----------------------------------------------------------------------------
656 #-----------------------------------------------------------------------------
590 # Aliases and Flags for the IPKernelApp
657 # Aliases and Flags for the IPKernelApp
591 #-----------------------------------------------------------------------------
658 #-----------------------------------------------------------------------------
592
659
593 flags = dict(kernel_flags)
660 flags = dict(kernel_flags)
594 flags.update(shell_flags)
661 flags.update(shell_flags)
595
662
596 addflag = lambda *args: flags.update(boolean_flag(*args))
663 addflag = lambda *args: flags.update(boolean_flag(*args))
597
664
598 flags['pylab'] = (
665 flags['pylab'] = (
599 {'IPKernelApp' : {'pylab' : 'auto'}},
666 {'IPKernelApp' : {'pylab' : 'auto'}},
600 """Pre-load matplotlib and numpy for interactive use with
667 """Pre-load matplotlib and numpy for interactive use with
601 the default matplotlib backend."""
668 the default matplotlib backend."""
602 )
669 )
603
670
604 aliases = dict(kernel_aliases)
671 aliases = dict(kernel_aliases)
605 aliases.update(shell_aliases)
672 aliases.update(shell_aliases)
606
673
607 # it's possible we don't want short aliases for *all* of these:
674 # it's possible we don't want short aliases for *all* of these:
608 aliases.update(dict(
675 aliases.update(dict(
609 pylab='IPKernelApp.pylab',
676 pylab='IPKernelApp.pylab',
610 ))
677 ))
611
678
612 #-----------------------------------------------------------------------------
679 #-----------------------------------------------------------------------------
613 # The IPKernelApp class
680 # The IPKernelApp class
614 #-----------------------------------------------------------------------------
681 #-----------------------------------------------------------------------------
615
682
616 class IPKernelApp(KernelApp, InteractiveShellApp):
683 class IPKernelApp(KernelApp, InteractiveShellApp):
617 name = 'ipkernel'
684 name = 'ipkernel'
618
685
619 aliases = Dict(aliases)
686 aliases = Dict(aliases)
620 flags = Dict(flags)
687 flags = Dict(flags)
621 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
688 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
622 # configurables
689 # configurables
623 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
690 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
624 config=True,
691 config=True,
625 help="""Pre-load matplotlib and numpy for interactive use,
692 help="""Pre-load matplotlib and numpy for interactive use,
626 selecting a particular matplotlib backend and loop integration.
693 selecting a particular matplotlib backend and loop integration.
627 """
694 """
628 )
695 )
629 def initialize(self, argv=None):
696 def initialize(self, argv=None):
630 super(IPKernelApp, self).initialize(argv)
697 super(IPKernelApp, self).initialize(argv)
631 self.init_shell()
698 self.init_shell()
632 self.init_extensions()
699 self.init_extensions()
633 self.init_code()
700 self.init_code()
634
701
635 def init_kernel(self):
702 def init_kernel(self):
636 kernel_factory = Kernel
703 kernel_factory = Kernel
637
704
638 kernel_map = {
705 kernel_map = {
639 'qt' : QtKernel,
706 'qt' : QtKernel,
640 'qt4': QtKernel,
707 'qt4': QtKernel,
641 'inline': Kernel,
708 'inline': Kernel,
642 'osx': TkKernel,
709 'osx': OSXKernel,
643 'wx' : WxKernel,
710 'wx' : WxKernel,
644 'tk' : TkKernel,
711 'tk' : TkKernel,
645 'gtk': GTKKernel,
712 'gtk': GTKKernel,
646 }
713 }
647
714
648 if self.pylab:
715 if self.pylab:
649 key = None if self.pylab == 'auto' else self.pylab
716 key = None if self.pylab == 'auto' else self.pylab
650 gui, backend = pylabtools.find_gui_and_backend(key)
717 gui, backend = pylabtools.find_gui_and_backend(key)
651 kernel_factory = kernel_map.get(gui)
718 kernel_factory = kernel_map.get(gui)
652 if kernel_factory is None:
719 if kernel_factory is None:
653 raise ValueError('GUI is not supported: %r' % gui)
720 raise ValueError('GUI is not supported: %r' % gui)
654 pylabtools.activate_matplotlib(backend)
721 pylabtools.activate_matplotlib(backend)
655
722
656 kernel = kernel_factory(config=self.config, session=self.session,
723 kernel = kernel_factory(config=self.config, session=self.session,
657 shell_socket=self.shell_socket,
724 shell_socket=self.shell_socket,
658 iopub_socket=self.iopub_socket,
725 iopub_socket=self.iopub_socket,
659 stdin_socket=self.stdin_socket,
726 stdin_socket=self.stdin_socket,
660 log=self.log
727 log=self.log
661 )
728 )
662 self.kernel = kernel
729 self.kernel = kernel
663 kernel.record_ports(self.ports)
730 kernel.record_ports(self.ports)
664
731
665 if self.pylab:
732 if self.pylab:
666 import_all = self.pylab_import_all
733 import_all = self.pylab_import_all
667 pylabtools.import_pylab(kernel.shell.user_ns, backend, import_all,
734 pylabtools.import_pylab(kernel.shell.user_ns, backend, import_all,
668 shell=kernel.shell)
735 shell=kernel.shell)
669
736
670 def init_shell(self):
737 def init_shell(self):
671 self.shell = self.kernel.shell
738 self.shell = self.kernel.shell
672
739
673
740
674 #-----------------------------------------------------------------------------
741 #-----------------------------------------------------------------------------
675 # Kernel main and launch functions
742 # Kernel main and launch functions
676 #-----------------------------------------------------------------------------
743 #-----------------------------------------------------------------------------
677
744
678 def launch_kernel(*args, **kwargs):
745 def launch_kernel(*args, **kwargs):
679 """Launches a localhost IPython kernel, binding to the specified ports.
746 """Launches a localhost IPython kernel, binding to the specified ports.
680
747
681 This function simply calls entry_point.base_launch_kernel with the right first
748 This function simply calls entry_point.base_launch_kernel with the right first
682 command to start an ipkernel. See base_launch_kernel for arguments.
749 command to start an ipkernel. See base_launch_kernel for arguments.
683
750
684 Returns
751 Returns
685 -------
752 -------
686 A tuple of form:
753 A tuple of form:
687 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
754 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
688 where kernel_process is a Popen object and the ports are integers.
755 where kernel_process is a Popen object and the ports are integers.
689 """
756 """
690 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
757 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
691 *args, **kwargs)
758 *args, **kwargs)
692
759
693
760
694 def main():
761 def main():
695 """Run an IPKernel as an application"""
762 """Run an IPKernel as an application"""
696 app = IPKernelApp.instance()
763 app = IPKernelApp.instance()
697 app.initialize()
764 app.initialize()
698 app.start()
765 app.start()
699
766
700
767
701 if __name__ == '__main__':
768 if __name__ == '__main__':
702 main()
769 main()
@@ -1,490 +1,490 b''
1 .. _qtconsole:
1 .. _qtconsole:
2
2
3 =========================
3 =========================
4 A Qt Console for IPython
4 A Qt Console for IPython
5 =========================
5 =========================
6
6
7 We now have a version of IPython, using the new two-process :ref:`ZeroMQ Kernel
7 We now have a version of IPython, using the new two-process :ref:`ZeroMQ Kernel
8 <ipythonzmq>`, running in a PyQt_ GUI. This is a very lightweight widget that
8 <ipythonzmq>`, running in a PyQt_ GUI. This is a very lightweight widget that
9 largely feels like a terminal, but provides a number of enhancements only
9 largely feels like a terminal, but provides a number of enhancements only
10 possible in a GUI, such as inline figures, proper multiline editing with syntax
10 possible in a GUI, such as inline figures, proper multiline editing with syntax
11 highlighting, graphical calltips, and much more.
11 highlighting, graphical calltips, and much more.
12
12
13 .. figure:: ../_static/qtconsole.png
13 .. figure:: ../_static/qtconsole.png
14 :width: 400px
14 :width: 400px
15 :alt: IPython Qt console with embedded plots
15 :alt: IPython Qt console with embedded plots
16 :align: center
16 :align: center
17 :target: ../_static/qtconsole.png
17 :target: ../_static/qtconsole.png
18
18
19 The Qt console for IPython, using inline matplotlib plots.
19 The Qt console for IPython, using inline matplotlib plots.
20
20
21 To get acquainted with the Qt console, type `%guiref` to see a quick
21 To get acquainted with the Qt console, type `%guiref` to see a quick
22 introduction of its main features.
22 introduction of its main features.
23
23
24 The Qt frontend has hand-coded emacs-style bindings for text navigation. This
24 The Qt frontend has hand-coded emacs-style bindings for text navigation. This
25 is not yet configurable.
25 is not yet configurable.
26
26
27 .. tip::
27 .. tip::
28
28
29 Since the Qt console tries hard to behave like a terminal, by default it
29 Since the Qt console tries hard to behave like a terminal, by default it
30 immediately executes single lines of input that are complete. If you want
30 immediately executes single lines of input that are complete. If you want
31 to force multiline input, hit :kbd:`Ctrl-Enter` at the end of the first line
31 to force multiline input, hit :kbd:`Ctrl-Enter` at the end of the first line
32 instead of :kbd:`Enter`, and it will open a new line for input. At any
32 instead of :kbd:`Enter`, and it will open a new line for input. At any
33 point in a multiline block, you can force its execution (without having to
33 point in a multiline block, you can force its execution (without having to
34 go to the bottom) with :kbd:`Shift-Enter`.
34 go to the bottom) with :kbd:`Shift-Enter`.
35
35
36 ``%loadpy``
36 ``%loadpy``
37 ===========
37 ===========
38
38
39 The new ``%loadpy`` magic takes any python script (must end in '.py'), and
39 The new ``%loadpy`` magic takes any python script (must end in '.py'), and
40 pastes its contents as your next input, so you can edit it before
40 pastes its contents as your next input, so you can edit it before
41 executing. The script may be on your machine, but you can also specify a url,
41 executing. The script may be on your machine, but you can also specify a url,
42 and it will download the script from the web. This is particularly useful for
42 and it will download the script from the web. This is particularly useful for
43 playing with examples from documentation, such as matplotlib.
43 playing with examples from documentation, such as matplotlib.
44
44
45 .. sourcecode:: ipython
45 .. sourcecode:: ipython
46
46
47 In [6]: %loadpy http://matplotlib.sourceforge.net/plot_directive/mpl_examples/mplot3d/contour3d_demo.py
47 In [6]: %loadpy http://matplotlib.sourceforge.net/plot_directive/mpl_examples/mplot3d/contour3d_demo.py
48
48
49 In [7]: from mpl_toolkits.mplot3d import axes3d
49 In [7]: from mpl_toolkits.mplot3d import axes3d
50 ...: import matplotlib.pyplot as plt
50 ...: import matplotlib.pyplot as plt
51 ...:
51 ...:
52 ...: fig = plt.figure()
52 ...: fig = plt.figure()
53 ...: ax = fig.add_subplot(111, projection='3d')
53 ...: ax = fig.add_subplot(111, projection='3d')
54 ...: X, Y, Z = axes3d.get_test_data(0.05)
54 ...: X, Y, Z = axes3d.get_test_data(0.05)
55 ...: cset = ax.contour(X, Y, Z)
55 ...: cset = ax.contour(X, Y, Z)
56 ...: ax.clabel(cset, fontsize=9, inline=1)
56 ...: ax.clabel(cset, fontsize=9, inline=1)
57 ...:
57 ...:
58 ...: plt.show()
58 ...: plt.show()
59
59
60 Pylab
60 Pylab
61 =====
61 =====
62
62
63 One of the most exciting features of the new console is embedded matplotlib
63 One of the most exciting features of the new console is embedded matplotlib
64 figures. You can use any standard matplotlib GUI backend (Except native MacOSX)
64 figures. You can use any standard matplotlib GUI backend
65 to draw the figures, and since there is now a two-process model, there is no
65 to draw the figures, and since there is now a two-process model, there is no
66 longer a conflict between user input and the drawing eventloop.
66 longer a conflict between user input and the drawing eventloop.
67
67
68 .. image:: figs/besselj.png
68 .. image:: figs/besselj.png
69 :width: 519px
69 :width: 519px
70
70
71 .. display:
71 .. display:
72
72
73 :func:`display`
73 :func:`display`
74 ***************
74 ***************
75
75
76 An additional function, :func:`display`, will be added to the global namespace
76 An additional function, :func:`display`, will be added to the global namespace
77 if you specify the ``--pylab`` option at the command line. The IPython display
77 if you specify the ``--pylab`` option at the command line. The IPython display
78 system provides a mechanism for specifying PNG or SVG (and more)
78 system provides a mechanism for specifying PNG or SVG (and more)
79 representations of objects for GUI frontends. By default, IPython registers
79 representations of objects for GUI frontends. By default, IPython registers
80 convenient PNG and SVG renderers for matplotlib figures, so you can embed them
80 convenient PNG and SVG renderers for matplotlib figures, so you can embed them
81 in your document by calling :func:`display` on one or more of them. This is
81 in your document by calling :func:`display` on one or more of them. This is
82 especially useful for saving_ your work.
82 especially useful for saving_ your work.
83
83
84 .. sourcecode:: ipython
84 .. sourcecode:: ipython
85
85
86 In [5]: plot(range(5)) # plots in the matplotlib window
86 In [5]: plot(range(5)) # plots in the matplotlib window
87
87
88 In [6]: display(gcf()) # embeds the current figure in the qtconsole
88 In [6]: display(gcf()) # embeds the current figure in the qtconsole
89
89
90 In [7]: display(*getfigs()) # embeds all active figures in the qtconsole
90 In [7]: display(*getfigs()) # embeds all active figures in the qtconsole
91
91
92 If you have a reference to a matplotlib figure object, you can always display
92 If you have a reference to a matplotlib figure object, you can always display
93 that specific figure:
93 that specific figure:
94
94
95 .. sourcecode:: ipython
95 .. sourcecode:: ipython
96
96
97 In [1]: f = figure()
97 In [1]: f = figure()
98
98
99 In [2]: plot(rand(100))
99 In [2]: plot(rand(100))
100 Out[2]: [<matplotlib.lines.Line2D at 0x7fc6ac03dd90>]
100 Out[2]: [<matplotlib.lines.Line2D at 0x7fc6ac03dd90>]
101
101
102 In [3]: display(f)
102 In [3]: display(f)
103
103
104 # Plot is shown here
104 # Plot is shown here
105
105
106 In [4]: title('A title')
106 In [4]: title('A title')
107 Out[4]: <matplotlib.text.Text at 0x7fc6ac023450>
107 Out[4]: <matplotlib.text.Text at 0x7fc6ac023450>
108
108
109 In [5]: display(f)
109 In [5]: display(f)
110
110
111 # Updated plot with title is shown here.
111 # Updated plot with title is shown here.
112
112
113 .. _inline:
113 .. _inline:
114
114
115 ``--pylab=inline``
115 ``--pylab=inline``
116 ******************
116 ******************
117
117
118 If you want to have all of your figures embedded in your session, instead of
118 If you want to have all of your figures embedded in your session, instead of
119 calling :func:`display`, you can specify ``--pylab=inline`` when you start the
119 calling :func:`display`, you can specify ``--pylab=inline`` when you start the
120 console, and each time you make a plot, it will show up in your document, as if
120 console, and each time you make a plot, it will show up in your document, as if
121 you had called :func:`display(fig)`.
121 you had called :func:`display(fig)`.
122
122
123
123
124 .. _saving:
124 .. _saving:
125
125
126 Saving and Printing
126 Saving and Printing
127 ===================
127 ===================
128
128
129 IPythonQt has the ability to save your current session, as either HTML or
129 IPythonQt has the ability to save your current session, as either HTML or
130 XHTML. If you have been using :func:`display` or inline_ pylab, your figures
130 XHTML. If you have been using :func:`display` or inline_ pylab, your figures
131 will be PNG in HTML, or inlined as SVG in XHTML. PNG images have the option to
131 will be PNG in HTML, or inlined as SVG in XHTML. PNG images have the option to
132 be either in an external folder, as in many browsers' "Webpage, Complete"
132 be either in an external folder, as in many browsers' "Webpage, Complete"
133 option, or inlined as well, for a larger, but more portable file.
133 option, or inlined as well, for a larger, but more portable file.
134
134
135 The widget also exposes the ability to print directly, via the default print
135 The widget also exposes the ability to print directly, via the default print
136 shortcut or context menu.
136 shortcut or context menu.
137
137
138
138
139 .. Note::
139 .. Note::
140
140
141 Saving is only available to richtext Qt widgets, which are used by default,
141 Saving is only available to richtext Qt widgets, which are used by default,
142 but if you pass the ``--plain`` flag, saving will not be available to you.
142 but if you pass the ``--plain`` flag, saving will not be available to you.
143
143
144
144
145 See these examples of :download:`png/html<figs/jn.html>` and
145 See these examples of :download:`png/html<figs/jn.html>` and
146 :download:`svg/xhtml <figs/jn.xhtml>` output. Note that syntax highlighting
146 :download:`svg/xhtml <figs/jn.xhtml>` output. Note that syntax highlighting
147 does not survive export. This is a known issue, and is being investigated.
147 does not survive export. This is a known issue, and is being investigated.
148
148
149 Colors and Highlighting
149 Colors and Highlighting
150 =======================
150 =======================
151
151
152 Terminal IPython has always had some coloring, but never syntax
152 Terminal IPython has always had some coloring, but never syntax
153 highlighting. There are a few simple color choices, specified by the ``colors``
153 highlighting. There are a few simple color choices, specified by the ``colors``
154 flag or ``%colors`` magic:
154 flag or ``%colors`` magic:
155
155
156 * LightBG for light backgrounds
156 * LightBG for light backgrounds
157 * Linux for dark backgrounds
157 * Linux for dark backgrounds
158 * NoColor for a simple colorless terminal
158 * NoColor for a simple colorless terminal
159
159
160 The Qt widget has full support for the ``colors`` flag used in the terminal shell.
160 The Qt widget has full support for the ``colors`` flag used in the terminal shell.
161
161
162 The Qt widget, however, has full syntax highlighting as you type, handled by
162 The Qt widget, however, has full syntax highlighting as you type, handled by
163 the `pygments`_ library. The ``style`` argument exposes access to any style by
163 the `pygments`_ library. The ``style`` argument exposes access to any style by
164 name that can be found by pygments, and there are several already
164 name that can be found by pygments, and there are several already
165 installed. The ``colors`` argument, if unspecified, will be guessed based on
165 installed. The ``colors`` argument, if unspecified, will be guessed based on
166 the chosen style. Similarly, there are default styles associated with each
166 the chosen style. Similarly, there are default styles associated with each
167 ``colors`` option.
167 ``colors`` option.
168
168
169
169
170 Screenshot of ``ipython qtconsole --colors=linux``, which uses the 'monokai'
170 Screenshot of ``ipython qtconsole --colors=linux``, which uses the 'monokai'
171 theme by default:
171 theme by default:
172
172
173 .. image:: figs/colors_dark.png
173 .. image:: figs/colors_dark.png
174 :width: 627px
174 :width: 627px
175
175
176 .. Note::
176 .. Note::
177
177
178 Calling ``ipython qtconsole -h`` will show all the style names that
178 Calling ``ipython qtconsole -h`` will show all the style names that
179 pygments can find on your system.
179 pygments can find on your system.
180
180
181 You can also pass the filename of a custom CSS stylesheet, if you want to do
181 You can also pass the filename of a custom CSS stylesheet, if you want to do
182 your own coloring, via the ``stylesheet`` argument. The default LightBG
182 your own coloring, via the ``stylesheet`` argument. The default LightBG
183 stylesheet:
183 stylesheet:
184
184
185 .. sourcecode:: css
185 .. sourcecode:: css
186
186
187 QPlainTextEdit, QTextEdit { background-color: white;
187 QPlainTextEdit, QTextEdit { background-color: white;
188 color: black ;
188 color: black ;
189 selection-background-color: #ccc}
189 selection-background-color: #ccc}
190 .error { color: red; }
190 .error { color: red; }
191 .in-prompt { color: navy; }
191 .in-prompt { color: navy; }
192 .in-prompt-number { font-weight: bold; }
192 .in-prompt-number { font-weight: bold; }
193 .out-prompt { color: darkred; }
193 .out-prompt { color: darkred; }
194 .out-prompt-number { font-weight: bold; }
194 .out-prompt-number { font-weight: bold; }
195
195
196 Fonts
196 Fonts
197 =====
197 =====
198
198
199 The QtConsole has configurable via the ConsoleWidget. To change these, set the
199 The QtConsole has configurable via the ConsoleWidget. To change these, set the
200 ``font_family`` or ``font_size`` traits of the ConsoleWidget. For instance, to
200 ``font_family`` or ``font_size`` traits of the ConsoleWidget. For instance, to
201 use 9pt Anonymous Pro::
201 use 9pt Anonymous Pro::
202
202
203 $> ipython qtconsole --ConsoleWidget.font_family="Anonymous Pro" --ConsoleWidget.font_size=9
203 $> ipython qtconsole --ConsoleWidget.font_family="Anonymous Pro" --ConsoleWidget.font_size=9
204
204
205 Process Management
205 Process Management
206 ==================
206 ==================
207
207
208 With the two-process ZMQ model, the frontend does not block input during
208 With the two-process ZMQ model, the frontend does not block input during
209 execution. This means that actions can be taken by the frontend while the
209 execution. This means that actions can be taken by the frontend while the
210 Kernel is executing, or even after it crashes. The most basic such command is
210 Kernel is executing, or even after it crashes. The most basic such command is
211 via 'Ctrl-.', which restarts the kernel. This can be done in the middle of a
211 via 'Ctrl-.', which restarts the kernel. This can be done in the middle of a
212 blocking execution. The frontend can also know, via a heartbeat mechanism, that
212 blocking execution. The frontend can also know, via a heartbeat mechanism, that
213 the kernel has died. This means that the frontend can safely restart the
213 the kernel has died. This means that the frontend can safely restart the
214 kernel.
214 kernel.
215
215
216 .. _multiple_consoles:
216 .. _multiple_consoles:
217
217
218 Multiple Consoles
218 Multiple Consoles
219 *****************
219 *****************
220
220
221 Since the Kernel listens on the network, multiple frontends can connect to it.
221 Since the Kernel listens on the network, multiple frontends can connect to it.
222 These do not have to all be qt frontends - any IPython frontend can connect and
222 These do not have to all be qt frontends - any IPython frontend can connect and
223 run code. When you start ipython qtconsole, there will be an output line,
223 run code. When you start ipython qtconsole, there will be an output line,
224 like::
224 like::
225
225
226 [IPKernelApp] To connect another client to this kernel, use:
226 [IPKernelApp] To connect another client to this kernel, use:
227 [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797
227 [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797
228
228
229 Other frontends can connect to your kernel, and share in the execution. This is
229 Other frontends can connect to your kernel, and share in the execution. This is
230 great for collaboration. The ``--existing`` flag means connect to a kernel
230 great for collaboration. The ``--existing`` flag means connect to a kernel
231 that already exists. Starting other
231 that already exists. Starting other
232 consoles with that flag will not try to start their own, but rather connect to
232 consoles with that flag will not try to start their own, but rather connect to
233 yours. Ultimately, you will not have to specify each port individually, but for
233 yours. Ultimately, you will not have to specify each port individually, but for
234 now this copy-paste method is best.
234 now this copy-paste method is best.
235
235
236 You can even launch a standalone kernel, and connect and disconnect Qt Consoles
236 You can even launch a standalone kernel, and connect and disconnect Qt Consoles
237 from various machines. This lets you keep the same running IPython session
237 from various machines. This lets you keep the same running IPython session
238 on your work machine (with matplotlib plots and everything), logging in from home,
238 on your work machine (with matplotlib plots and everything), logging in from home,
239 cafΓ©s, etc.::
239 cafΓ©s, etc.::
240
240
241 $> ipython kernel
241 $> ipython kernel
242 [IPKernelApp] To connect another client to this kernel, use:
242 [IPKernelApp] To connect another client to this kernel, use:
243 [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797
243 [IPKernelApp] --existing --shell=60690 --iopub=44045 --stdin=38323 --hb=41797
244
244
245 This is actually exactly the same as the subprocess launched by the qtconsole, so
245 This is actually exactly the same as the subprocess launched by the qtconsole, so
246 all the information about connecting to a standalone kernel is identical to that
246 all the information about connecting to a standalone kernel is identical to that
247 of connecting to the kernel attached to a running console.
247 of connecting to the kernel attached to a running console.
248
248
249 .. _kernel_security:
249 .. _kernel_security:
250
250
251 Security
251 Security
252 --------
252 --------
253
253
254 .. warning::
254 .. warning::
255
255
256 Since the ZMQ code currently has no security, listening on an
256 Since the ZMQ code currently has no security, listening on an
257 external-facing IP is dangerous. You are giving any computer that can see
257 external-facing IP is dangerous. You are giving any computer that can see
258 you on the network the ability to issue arbitrary shell commands as you on
258 you on the network the ability to issue arbitrary shell commands as you on
259 your machine. Read the rest of this section before listening on external ports
259 your machine. Read the rest of this section before listening on external ports
260 or running an IPython kernel on a shared machine.
260 or running an IPython kernel on a shared machine.
261
261
262 By default (for security reasons), the kernel only listens on localhost, so you
262 By default (for security reasons), the kernel only listens on localhost, so you
263 can only connect multiple frontends to the kernel from your local machine. You
263 can only connect multiple frontends to the kernel from your local machine. You
264 can specify to listen on an external interface by specifying the ``ip``
264 can specify to listen on an external interface by specifying the ``ip``
265 argument::
265 argument::
266
266
267 $> ipython qtconsole --ip=192.168.1.123
267 $> ipython qtconsole --ip=192.168.1.123
268
268
269 If you specify the ip as 0.0.0.0, that refers to all interfaces, so any
269 If you specify the ip as 0.0.0.0, that refers to all interfaces, so any
270 computer that can see yours on the network can connect to the kernel.
270 computer that can see yours on the network can connect to the kernel.
271
271
272 Messages are not encrypted, so users with access to the ports your kernel is using will be
272 Messages are not encrypted, so users with access to the ports your kernel is using will be
273 able to see any output of the kernel. They will also be able to issue shell commands as
273 able to see any output of the kernel. They will also be able to issue shell commands as
274 you, unless you enable HMAC digests, which are **DISABLED** by default.
274 you, unless you enable HMAC digests, which are **DISABLED** by default.
275
275
276 The one security feature IPython does provide is protection from unauthorized
276 The one security feature IPython does provide is protection from unauthorized
277 execution. IPython's messaging system can sign messages with HMAC digests using
277 execution. IPython's messaging system can sign messages with HMAC digests using
278 a shared-key. The key is never sent over the network, it is only used to generate
278 a shared-key. The key is never sent over the network, it is only used to generate
279 a unique hash for each message, based on its content. When IPython receives a
279 a unique hash for each message, based on its content. When IPython receives a
280 message, it will check that the digest matches. You can use any file that only you
280 message, it will check that the digest matches. You can use any file that only you
281 have access to to generate this key. One logical choice would be to use your own
281 have access to to generate this key. One logical choice would be to use your own
282 SSH private key. Or you can generate a new random private key with::
282 SSH private key. Or you can generate a new random private key with::
283
283
284 # generate 1024b of random data, and store in a file only you can read:
284 # generate 1024b of random data, and store in a file only you can read:
285 # (assumes IPYTHON_DIR is defined, otherwise use your IPython directory)
285 # (assumes IPYTHON_DIR is defined, otherwise use your IPython directory)
286 $> python -c "import os; print os.urandom(128).encode('base64')" > $IPYTHON_DIR/sessionkey
286 $> python -c "import os; print os.urandom(128).encode('base64')" > $IPYTHON_DIR/sessionkey
287 $> chmod 600 $IPYTHON_DIR/sessionkey
287 $> chmod 600 $IPYTHON_DIR/sessionkey
288
288
289 To enable HMAC digests, simply specify the ``Session.keyfile`` configurable
289 To enable HMAC digests, simply specify the ``Session.keyfile`` configurable
290 in :file:`ipython_config.py` or at the command-line, as in::
290 in :file:`ipython_config.py` or at the command-line, as in::
291
291
292 # instruct IPython to sign messages with that key:
292 # instruct IPython to sign messages with that key:
293 $> ipython qtconsole --Session.keyfile=$IPYTHON_DIR/sessionkey
293 $> ipython qtconsole --Session.keyfile=$IPYTHON_DIR/sessionkey
294
294
295 You must use the same key you used to start the kernel with all frontends, or
295 You must use the same key you used to start the kernel with all frontends, or
296 they will be treated as an unauthorized peer (all messages will be ignored).
296 they will be treated as an unauthorized peer (all messages will be ignored).
297
297
298 .. note::
298 .. note::
299
299
300 IPython will move to using files to store connection information, as is
300 IPython will move to using files to store connection information, as is
301 done in :mod:`IPython.parallel`, at which point HMAC signatures will be
301 done in :mod:`IPython.parallel`, at which point HMAC signatures will be
302 enabled *by default*.
302 enabled *by default*.
303
303
304 .. _ssh_tunnels:
304 .. _ssh_tunnels:
305
305
306 SSH Tunnels
306 SSH Tunnels
307 -----------
307 -----------
308
308
309 Sometimes you want to connect to machines across the internet, or just across
309 Sometimes you want to connect to machines across the internet, or just across
310 a LAN that either doesn't permit open ports or you don't trust the other
310 a LAN that either doesn't permit open ports or you don't trust the other
311 machines on the network. To do this, you can use SSH tunnels. SSH tunnels
311 machines on the network. To do this, you can use SSH tunnels. SSH tunnels
312 are a way to securely forward ports on your local machine to ports on another
312 are a way to securely forward ports on your local machine to ports on another
313 machine, to which you have SSH access.
313 machine, to which you have SSH access.
314
314
315 In simple cases, IPython's tools can forward ports over ssh by simply adding the
315 In simple cases, IPython's tools can forward ports over ssh by simply adding the
316 ``--ssh=remote`` argument to the usual ``--existing...`` set of flags for connecting
316 ``--ssh=remote`` argument to the usual ``--existing...`` set of flags for connecting
317 to a running kernel.
317 to a running kernel.
318
318
319 .. warning::
319 .. warning::
320
320
321 Using SSH tunnels does *not* increase localhost security. In fact, when
321 Using SSH tunnels does *not* increase localhost security. In fact, when
322 tunneling from one machine to another *both* machines have open
322 tunneling from one machine to another *both* machines have open
323 ports on localhost available for connections.
323 ports on localhost available for connections.
324
324
325 There are two primary models for using SSH tunnels with IPython. The first
325 There are two primary models for using SSH tunnels with IPython. The first
326 is to have the Kernel listen only on localhost, and connect to it from
326 is to have the Kernel listen only on localhost, and connect to it from
327 another machine on the same LAN.
327 another machine on the same LAN.
328
328
329 First, let's start a kernel on machine **worker**, listening only
329 First, let's start a kernel on machine **worker**, listening only
330 on loopback::
330 on loopback::
331
331
332 user@worker $> ipython kernel
332 user@worker $> ipython kernel
333 [IPKernelApp] To connect another client to this kernel, use:
333 [IPKernelApp] To connect another client to this kernel, use:
334 [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
334 [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
335
335
336 In this case, the IP that you would connect
336 In this case, the IP that you would connect
337 to would still be 127.0.0.1, but you want to specify the additional ``--ssh`` argument
337 to would still be 127.0.0.1, but you want to specify the additional ``--ssh`` argument
338 with the hostname of the kernel (in this example, it's 'worker')::
338 with the hostname of the kernel (in this example, it's 'worker')::
339
339
340 user@client $> ipython qtconsole --ssh=worker --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
340 user@client $> ipython qtconsole --ssh=worker --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
341
341
342 Note again that this opens ports on the *client* machine that point to your kernel.
342 Note again that this opens ports on the *client* machine that point to your kernel.
343 Be sure to use a Session key, as described above, if localhost on *either* the
343 Be sure to use a Session key, as described above, if localhost on *either* the
344 client or kernel machines is untrusted.
344 client or kernel machines is untrusted.
345
345
346 .. note::
346 .. note::
347
347
348 the ssh argument is simply passed to openssh, so it can be fully specified ``user@host:port``
348 the ssh argument is simply passed to openssh, so it can be fully specified ``user@host:port``
349 but it will also respect your aliases, etc. in :file:`.ssh/config` if you have any.
349 but it will also respect your aliases, etc. in :file:`.ssh/config` if you have any.
350
350
351 The second pattern is for connecting to a machine behind a firewall across the internet
351 The second pattern is for connecting to a machine behind a firewall across the internet
352 (or otherwise wide network). This time, we have a machine **login** that you have ssh access
352 (or otherwise wide network). This time, we have a machine **login** that you have ssh access
353 to, which can see **kernel**, but **client** is on another network. The important difference
353 to, which can see **kernel**, but **client** is on another network. The important difference
354 now is that **client** can see **login**, but *not* **worker**. So we need to forward ports from
354 now is that **client** can see **login**, but *not* **worker**. So we need to forward ports from
355 client to worker *via* login. This means that the kernel must be started listening
355 client to worker *via* login. This means that the kernel must be started listening
356 on external interfaces, so that its ports are visible to `login`::
356 on external interfaces, so that its ports are visible to `login`::
357
357
358 user@worker $> ipython kernel --ip=0.0.0.0
358 user@worker $> ipython kernel --ip=0.0.0.0
359 [IPKernelApp] To connect another client to this kernel, use:
359 [IPKernelApp] To connect another client to this kernel, use:
360 [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
360 [IPKernelApp] --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
361
361
362 Which we can connect to from the client with::
362 Which we can connect to from the client with::
363
363
364 user@client $> ipython qtconsole --ssh=login --ip=192.168.1.123 --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
364 user@client $> ipython qtconsole --ssh=login --ip=192.168.1.123 --existing --shell=59480 --iopub=62199 --stdin=64898 --hb=56511
365
365
366 Note that now the IP is the address of worker as seen from login.
366 Note that now the IP is the address of worker as seen from login.
367
367
368 Manual SSH tunnels
368 Manual SSH tunnels
369 ------------------
369 ------------------
370
370
371 It's possible that IPython's ssh helper functions won't work for you, for various
371 It's possible that IPython's ssh helper functions won't work for you, for various
372 reasons. You can still connect to remote machines, as long as you set up the tunnels
372 reasons. You can still connect to remote machines, as long as you set up the tunnels
373 yourself. The basic format of forwarding a local port to a remote one is::
373 yourself. The basic format of forwarding a local port to a remote one is::
374
374
375 [client] $> ssh <server> <localport>:<remoteip>:<remoteport> -f -N
375 [client] $> ssh <server> <localport>:<remoteip>:<remoteport> -f -N
376
376
377 This will forward local connections to **localport** on client to **remoteip:remoteport**
377 This will forward local connections to **localport** on client to **remoteip:remoteport**
378 *via* **server**. Note that remoteip is interpreted relative to *server*, not the client.
378 *via* **server**. Note that remoteip is interpreted relative to *server*, not the client.
379 So if you have direct ssh access to the machine to which you want to forward connections,
379 So if you have direct ssh access to the machine to which you want to forward connections,
380 then the server *is* the remote machine, and remoteip should be server's IP as seen from the
380 then the server *is* the remote machine, and remoteip should be server's IP as seen from the
381 server itself, i.e. 127.0.0.1. Thus, to forward local port 12345 to remote port 54321 on
381 server itself, i.e. 127.0.0.1. Thus, to forward local port 12345 to remote port 54321 on
382 a machine you can see, do::
382 a machine you can see, do::
383
383
384 [client] $> ssh machine 12345:127.0.0.1:54321 -f -N
384 [client] $> ssh machine 12345:127.0.0.1:54321 -f -N
385
385
386 But if your target is actually on a LAN at 192.168.1.123, behind another machine called **login**,
386 But if your target is actually on a LAN at 192.168.1.123, behind another machine called **login**,
387 then you would do::
387 then you would do::
388
388
389 [client] $> ssh login 12345:192.168.1.16:54321 -f -N
389 [client] $> ssh login 12345:192.168.1.16:54321 -f -N
390
390
391 The ``-f -N`` on the end are flags that tell ssh to run in the background,
391 The ``-f -N`` on the end are flags that tell ssh to run in the background,
392 and don't actually run any commands beyond creating the tunnel.
392 and don't actually run any commands beyond creating the tunnel.
393
393
394 .. seealso::
394 .. seealso::
395
395
396 A short discussion of ssh tunnels: http://www.revsys.com/writings/quicktips/ssh-tunnel.html
396 A short discussion of ssh tunnels: http://www.revsys.com/writings/quicktips/ssh-tunnel.html
397
397
398
398
399
399
400 Stopping Kernels and Consoles
400 Stopping Kernels and Consoles
401 *****************************
401 *****************************
402
402
403 Since there can be many consoles per kernel, the shutdown mechanism and dialog
403 Since there can be many consoles per kernel, the shutdown mechanism and dialog
404 are probably more complicated than you are used to. Since you don't always want
404 are probably more complicated than you are used to. Since you don't always want
405 to shutdown a kernel when you close a window, you are given the option to just
405 to shutdown a kernel when you close a window, you are given the option to just
406 close the console window or also close the Kernel and *all other windows*. Note
406 close the console window or also close the Kernel and *all other windows*. Note
407 that this only refers to all other *local* windows, as remote Consoles are not
407 that this only refers to all other *local* windows, as remote Consoles are not
408 allowed to shutdown the kernel, and shutdowns do not close Remote consoles (to
408 allowed to shutdown the kernel, and shutdowns do not close Remote consoles (to
409 allow for saving, etc.).
409 allow for saving, etc.).
410
410
411 Rules:
411 Rules:
412
412
413 * Restarting the kernel automatically clears all *local* Consoles, and prompts remote
413 * Restarting the kernel automatically clears all *local* Consoles, and prompts remote
414 Consoles about the reset.
414 Consoles about the reset.
415 * Shutdown closes all *local* Consoles, and notifies remotes that
415 * Shutdown closes all *local* Consoles, and notifies remotes that
416 the Kernel has been shutdown.
416 the Kernel has been shutdown.
417 * Remote Consoles may not restart or shutdown the kernel.
417 * Remote Consoles may not restart or shutdown the kernel.
418
418
419 Qt and the QtConsole
419 Qt and the QtConsole
420 ====================
420 ====================
421
421
422 An important part of working with the QtConsole when you are writing your own
422 An important part of working with the QtConsole when you are writing your own
423 Qt code is to remember that user code (in the kernel) is *not* in the same
423 Qt code is to remember that user code (in the kernel) is *not* in the same
424 process as the frontend. This means that there is not necessarily any Qt code
424 process as the frontend. This means that there is not necessarily any Qt code
425 running in the kernel, and under most normal circumstances there isn't. If,
425 running in the kernel, and under most normal circumstances there isn't. If,
426 however, you specify ``--pylab=qt`` at the command-line, then there *will* be a
426 however, you specify ``--pylab=qt`` at the command-line, then there *will* be a
427 :class:`QCoreApplication` instance running in the kernel process along with
427 :class:`QCoreApplication` instance running in the kernel process along with
428 user-code. To get a reference to this application, do:
428 user-code. To get a reference to this application, do:
429
429
430 .. sourcecode:: python
430 .. sourcecode:: python
431
431
432 from PyQt4 import QtCore
432 from PyQt4 import QtCore
433 app = QtCore.QCoreApplication.instance()
433 app = QtCore.QCoreApplication.instance()
434 # app will be None if there is no such instance
434 # app will be None if there is no such instance
435
435
436 A common problem listed in the PyQt4 Gotchas_ is the fact that Python's garbage
436 A common problem listed in the PyQt4 Gotchas_ is the fact that Python's garbage
437 collection will destroy Qt objects (Windows, etc.) once there is no longer a
437 collection will destroy Qt objects (Windows, etc.) once there is no longer a
438 Python reference to them, so you have to hold on to them. For instance, in:
438 Python reference to them, so you have to hold on to them. For instance, in:
439
439
440 .. sourcecode:: python
440 .. sourcecode:: python
441
441
442 def make_window():
442 def make_window():
443 win = QtGui.QMainWindow()
443 win = QtGui.QMainWindow()
444
444
445 def make_and_return_window():
445 def make_and_return_window():
446 win = QtGui.QMainWindow()
446 win = QtGui.QMainWindow()
447 return win
447 return win
448
448
449 :func:`make_window` will never draw a window, because garbage collection will
449 :func:`make_window` will never draw a window, because garbage collection will
450 destroy it before it is drawn, whereas :func:`make_and_return_window` lets the
450 destroy it before it is drawn, whereas :func:`make_and_return_window` lets the
451 caller decide when the window object should be destroyed. If, as a developer,
451 caller decide when the window object should be destroyed. If, as a developer,
452 you know that you always want your objects to last as long as the process, you
452 you know that you always want your objects to last as long as the process, you
453 can attach them to the QApplication instance itself:
453 can attach them to the QApplication instance itself:
454
454
455 .. sourcecode:: python
455 .. sourcecode:: python
456
456
457 # do this just once:
457 # do this just once:
458 app = QtCore.QCoreApplication.instance()
458 app = QtCore.QCoreApplication.instance()
459 app.references = set()
459 app.references = set()
460 # then when you create Windows, add them to the set
460 # then when you create Windows, add them to the set
461 def make_window():
461 def make_window():
462 win = QtGui.QMainWindow()
462 win = QtGui.QMainWindow()
463 app.references.add(win)
463 app.references.add(win)
464
464
465 Now the QApplication itself holds a reference to ``win``, so it will never be
465 Now the QApplication itself holds a reference to ``win``, so it will never be
466 garbage collected until the application itself is destroyed.
466 garbage collected until the application itself is destroyed.
467
467
468 .. _Gotchas: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html#garbage-collection
468 .. _Gotchas: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html#garbage-collection
469
469
470 Regressions
470 Regressions
471 ===========
471 ===========
472
472
473 There are some features, where the qt console lags behind the Terminal
473 There are some features, where the qt console lags behind the Terminal
474 frontend:
474 frontend:
475
475
476 * !cmd input: Due to our use of pexpect, we cannot pass input to subprocesses
476 * !cmd input: Due to our use of pexpect, we cannot pass input to subprocesses
477 launched using the '!' escape, so you should never call a command that
477 launched using the '!' escape, so you should never call a command that
478 requires interactive input. For such cases, use the terminal IPython. This
478 requires interactive input. For such cases, use the terminal IPython. This
479 will not be fixed, as abandoning pexpect would significantly degrade the
479 will not be fixed, as abandoning pexpect would significantly degrade the
480 console experience.
480 console experience.
481
481
482 * Use of ``\b`` and ``\r`` characters in the console: these are control
482 * Use of ``\b`` and ``\r`` characters in the console: these are control
483 characters that allow the cursor to move backwards on a line, and are used to
483 characters that allow the cursor to move backwards on a line, and are used to
484 display things like in-place progress bars in a terminal. We currently do
484 display things like in-place progress bars in a terminal. We currently do
485 not support this, but it is being tracked as issue 629_.
485 not support this, but it is being tracked as issue 629_.
486
486
487 .. _629: https://github.com/ipython/ipython/issues/629
487 .. _629: https://github.com/ipython/ipython/issues/629
488
488
489 .. [PyQt] PyQt4 http://www.riverbankcomputing.co.uk/software/pyqt/download
489 .. [PyQt] PyQt4 http://www.riverbankcomputing.co.uk/software/pyqt/download
490 .. [pygments] Pygments http://pygments.org/
490 .. [pygments] Pygments http://pygments.org/
General Comments 0
You need to be logged in to leave comments. Login now