##// END OF EJS Templates
Merge pull request #4939 from takluyver/embed-qtconsole-docs...
Paul Ivanov -
r14994:1c16ef61 merge
parent child Browse files
Show More
@@ -1,610 +1,639 b''
1 1 .. _qtconsole:
2 2
3 3 =========================
4 4 A Qt Console for IPython
5 5 =========================
6 6
7 7 We now have a version of IPython, using the new two-process :ref:`ZeroMQ Kernel
8 8 <ipythonzmq>`, running in a PyQt_ GUI. This is a very lightweight widget that
9 9 largely feels like a terminal, but provides a number of enhancements only
10 10 possible in a GUI, such as inline figures, proper multiline editing with syntax
11 11 highlighting, graphical calltips, and much more.
12 12
13 13 .. figure:: ../_images/qtconsole.png
14 14 :width: 400px
15 15 :alt: IPython Qt console with embedded plots
16 16 :align: center
17 17 :target: ../_images/qtconsole.png
18 18
19 19 The Qt console for IPython, using inline matplotlib plots.
20 20
21 21 To get acquainted with the Qt console, type `%guiref` to see a quick
22 22 introduction of its main features.
23 23
24 24 The Qt frontend has hand-coded emacs-style bindings for text navigation. This
25 25 is not yet configurable.
26 26
27 27 .. tip::
28 28
29 29 Since the Qt console tries hard to behave like a terminal, by default it
30 30 immediately executes single lines of input that are complete. If you want
31 31 to force multiline input, hit :kbd:`Ctrl-Enter` at the end of the first line
32 32 instead of :kbd:`Enter`, and it will open a new line for input. At any
33 33 point in a multiline block, you can force its execution (without having to
34 34 go to the bottom) with :kbd:`Shift-Enter`.
35 35
36 36 ``%load``
37 37 =========
38 38
39 39 The new ``%load`` magic (previously ``%loadpy``) takes any script, and pastes
40 40 its contents as your next input, so you can edit it before executing. The
41 41 script may be on your machine, but you can also specify an history range, or a
42 42 url, and it will download the script from the web. This is particularly useful
43 43 for playing with examples from documentation, such as matplotlib.
44 44
45 45 .. sourcecode:: ipython
46 46
47 47 In [6]: %load http://matplotlib.org/plot_directive/mpl_examples/mplot3d/contour3d_demo.py
48 48
49 49 In [7]: from mpl_toolkits.mplot3d import axes3d
50 50 ...: import matplotlib.pyplot as plt
51 51 ...:
52 52 ...: fig = plt.figure()
53 53 ...: ax = fig.add_subplot(111, projection='3d')
54 54 ...: X, Y, Z = axes3d.get_test_data(0.05)
55 55 ...: cset = ax.contour(X, Y, Z)
56 56 ...: ax.clabel(cset, fontsize=9, inline=1)
57 57 ...:
58 58 ...: plt.show()
59 59
60 60 Inline Matplotlib
61 61 =================
62 62
63 63 One of the most exciting features of the QtConsole is embedded matplotlib
64 64 figures. You can use any standard matplotlib GUI backend
65 65 to draw the figures, and since there is now a two-process model, there is no
66 66 longer a conflict between user input and the drawing eventloop.
67 67
68 68 .. image:: figs/besselj.png
69 69 :width: 519px
70 70
71 71 .. _display:
72 72
73 73 :func:`display`
74 74 ***************
75 75
76 76 IPython provides a function :func:`display` for displaying rich representations
77 77 of objects if they are available. The IPython display
78 78 system provides a mechanism for specifying PNG or SVG (and more)
79 79 representations of objects for GUI frontends.
80 80 When you enable matplotlib integration via the ``%matplotlib`` magic, IPython registers
81 81 convenient PNG and SVG renderers for matplotlib figures, so you can embed them
82 82 in your document by calling :func:`display` on one or more of them. This is
83 83 especially useful for saving_ your work.
84 84
85 85 .. sourcecode:: ipython
86 86
87 87 In [4]: from IPython.display import display
88 88
89 89 In [5]: plt.plot(range(5)) # plots in the matplotlib window
90 90
91 91 In [6]: display(plt.gcf()) # embeds the current figure in the qtconsole
92 92
93 93 In [7]: display(*getfigs()) # embeds all active figures in the qtconsole
94 94
95 95 If you have a reference to a matplotlib figure object, you can always display
96 96 that specific figure:
97 97
98 98 .. sourcecode:: ipython
99 99
100 100 In [1]: f = plt.figure()
101 101
102 102 In [2]: plt.plot(np.rand(100))
103 103 Out[2]: [<matplotlib.lines.Line2D at 0x7fc6ac03dd90>]
104 104
105 105 In [3]: display(f)
106 106
107 107 # Plot is shown here
108 108
109 109 In [4]: plt.title('A title')
110 110 Out[4]: <matplotlib.text.Text at 0x7fc6ac023450>
111 111
112 112 In [5]: display(f)
113 113
114 114 # Updated plot with title is shown here.
115 115
116 116 .. _inline:
117 117
118 118 ``--matplotlib inline``
119 119 ***********************
120 120
121 121 If you want to have all of your figures embedded in your session, instead of
122 122 calling :func:`display`, you can specify ``--matplotlib inline`` when you start the
123 123 console, and each time you make a plot, it will show up in your document, as if
124 124 you had called :func:`display(fig)`.
125 125
126 126 The inline backend can use either SVG or PNG figures (PNG being the default).
127 127 It also supports the special key ``'retina'``, which is 2x PNG for high-DPI displays.
128 128 To switch between them, set the ``InlineBackend.figure_format`` configurable
129 129 in a config file, or via the ``%config`` magic:
130 130
131 131 .. sourcecode:: ipython
132 132
133 133 In [10]: %config InlineBackend.figure_format = 'svg'
134 134
135 135 .. note::
136 136
137 137 Changing the inline figure format also affects calls to :func:`display` above,
138 138 even if you are not using the inline backend for all figures.
139 139
140 140 By default, IPython closes all figures at the completion of each execution. This means you
141 141 don't have to manually close figures, which is less convenient when figures aren't attached
142 142 to windows with an obvious close button. It also means that the first matplotlib call in
143 143 each cell will always create a new figure:
144 144
145 145 .. sourcecode:: ipython
146 146
147 147 In [11]: plt.plot(range(100))
148 148 <single-line plot>
149 149
150 150 In [12]: plt.plot([1,3,2])
151 151 <another single-line plot>
152 152
153 153
154 154 However, it does prevent the list of active figures surviving from one input cell to the
155 155 next, so if you want to continue working with a figure, you must hold on to a reference to
156 156 it:
157 157
158 158 .. sourcecode:: ipython
159 159
160 160 In [11]: fig = gcf()
161 161 ....: fig.plot(rand(100))
162 162 <plot>
163 163 In [12]: fig.title('Random Title')
164 164 <redraw plot with title>
165 165
166 166 This behavior is controlled by the :attr:`InlineBackend.close_figures` configurable, and
167 167 if you set it to False, via %config or config file, then IPython will *not* close figures,
168 168 and tools like :func:`gcf`, :func:`gca`, :func:`getfigs` will behave the same as they
169 169 do with other backends. You will, however, have to manually close figures:
170 170
171 171 .. sourcecode:: ipython
172 172
173 173 # close all active figures:
174 174 In [13]: [ fig.close() for fig in getfigs() ]
175 175
176 176
177 177
178 178 .. _saving:
179 179
180 180 Saving and Printing
181 181 ===================
182 182
183 183 IPythonQt has the ability to save your current session, as either HTML or
184 184 XHTML. If you have been using :func:`display` or inline_ matplotlib, your figures
185 185 will be PNG in HTML, or inlined as SVG in XHTML. PNG images have the option to
186 186 be either in an external folder, as in many browsers' "Webpage, Complete"
187 187 option, or inlined as well, for a larger, but more portable file.
188 188
189 189 .. note::
190 190
191 191 Export to SVG+XHTML requires that you are using SVG figures, which is *not*
192 192 the default. To switch the inline figure format to use SVG during an active
193 193 session, do:
194 194
195 195 .. sourcecode:: ipython
196 196
197 197 In [10]: %config InlineBackend.figure_format = 'svg'
198 198
199 199 Or, you can add the same line (c.Inline... instead of %config Inline...) to
200 200 your config files.
201 201
202 202 This will only affect figures plotted after making this call
203 203
204 204
205 205 The widget also exposes the ability to print directly, via the default print
206 206 shortcut or context menu.
207 207
208 208
209 209 .. Note::
210 210
211 211 Saving is only available to richtext Qt widgets, which are used by default,
212 212 but if you pass the ``--plain`` flag, saving will not be available to you.
213 213
214 214
215 215 See these examples of :download:`png/html<figs/jn.html>` and
216 216 :download:`svg/xhtml <figs/jn.xhtml>` output. Note that syntax highlighting
217 217 does not survive export. This is a known issue, and is being investigated.
218 218
219 219
220 220 Colors and Highlighting
221 221 =======================
222 222
223 223 Terminal IPython has always had some coloring, but never syntax
224 224 highlighting. There are a few simple color choices, specified by the ``colors``
225 225 flag or ``%colors`` magic:
226 226
227 227 * LightBG for light backgrounds
228 228 * Linux for dark backgrounds
229 229 * NoColor for a simple colorless terminal
230 230
231 231 The Qt widget has full support for the ``colors`` flag used in the terminal shell.
232 232
233 233 The Qt widget, however, has full syntax highlighting as you type, handled by
234 234 the `pygments`_ library. The ``style`` argument exposes access to any style by
235 235 name that can be found by pygments, and there are several already
236 236 installed. The ``colors`` argument, if unspecified, will be guessed based on
237 237 the chosen style. Similarly, there are default styles associated with each
238 238 ``colors`` option.
239 239
240 240
241 241 Screenshot of ``ipython qtconsole --colors=linux``, which uses the 'monokai'
242 242 theme by default:
243 243
244 244 .. image:: figs/colors_dark.png
245 245 :width: 627px
246 246
247 247 .. Note::
248 248
249 249 Calling ``ipython qtconsole -h`` will show all the style names that
250 250 pygments can find on your system.
251 251
252 252 You can also pass the filename of a custom CSS stylesheet, if you want to do
253 253 your own coloring, via the ``stylesheet`` argument. The default LightBG
254 254 stylesheet:
255 255
256 256 .. sourcecode:: css
257 257
258 258 QPlainTextEdit, QTextEdit { background-color: white;
259 259 color: black ;
260 260 selection-background-color: #ccc}
261 261 .error { color: red; }
262 262 .in-prompt { color: navy; }
263 263 .in-prompt-number { font-weight: bold; }
264 264 .out-prompt { color: darkred; }
265 265 .out-prompt-number { font-weight: bold; }
266 266 /* .inverted is used to highlight selected completion */
267 267 .inverted { background-color: black ; color: white; }
268 268
269 269 Fonts
270 270 =====
271 271
272 272 The QtConsole has configurable via the ConsoleWidget. To change these, set the
273 273 ``font_family`` or ``font_size`` traits of the ConsoleWidget. For instance, to
274 274 use 9pt Anonymous Pro::
275 275
276 276 $> ipython qtconsole --ConsoleWidget.font_family="Anonymous Pro" --ConsoleWidget.font_size=9
277 277
278 278 Process Management
279 279 ==================
280 280
281 281 With the two-process ZMQ model, the frontend does not block input during
282 282 execution. This means that actions can be taken by the frontend while the
283 283 Kernel is executing, or even after it crashes. The most basic such command is
284 284 via 'Ctrl-.', which restarts the kernel. This can be done in the middle of a
285 285 blocking execution. The frontend can also know, via a heartbeat mechanism, that
286 286 the kernel has died. This means that the frontend can safely restart the
287 287 kernel.
288 288
289 289 .. _multiple_consoles:
290 290
291 291 Multiple Consoles
292 292 *****************
293 293
294 294 Since the Kernel listens on the network, multiple frontends can connect to it.
295 295 These do not have to all be qt frontends - any IPython frontend can connect and
296 296 run code. When you start ipython qtconsole, there will be an output line,
297 297 like::
298 298
299 299 [IPKernelApp] To connect another client to this kernel, use:
300 300 [IPKernelApp] --existing kernel-12345.json
301 301
302 302 Other frontends can connect to your kernel, and share in the execution. This is
303 303 great for collaboration. The ``--existing`` flag means connect to a kernel
304 304 that already exists. Starting other consoles
305 305 with that flag will not try to start their own kernel, but rather connect to
306 306 yours. :file:`kernel-12345.json` is a small JSON file with the ip, port, and
307 307 authentication information necessary to connect to your kernel. By default, this file
308 308 will be in your default profile's security directory. If it is somewhere else,
309 309 the output line will print the full path of the connection file, rather than
310 310 just its filename.
311 311
312 312 If you need to find the connection info to send, and don't know where your connection file
313 313 lives, there are a couple of ways to get it. If you are already running an IPython console
314 314 connected to the kernel, you can use the ``%connect_info`` magic to display the information
315 315 necessary to connect another frontend to the kernel.
316 316
317 317 .. sourcecode:: ipython
318 318
319 319 In [2]: %connect_info
320 320 {
321 321 "stdin_port":50255,
322 322 "ip":"127.0.0.1",
323 323 "hb_port":50256,
324 324 "key":"70be6f0f-1564-4218-8cda-31be40a4d6aa",
325 325 "shell_port":50253,
326 326 "iopub_port":50254
327 327 }
328 328
329 329 Paste the above JSON into a file, and connect with:
330 330 $> ipython <app> --existing <file>
331 331 or, if you are local, you can connect with just:
332 332 $> ipython <app> --existing kernel-12345.json
333 333 or even just:
334 334 $> ipython <app> --existing
335 335 if this is the most recent IPython session you have started.
336 336
337 337 Otherwise, you can find a connection file by name (and optionally profile) with
338 338 :func:`IPython.lib.kernel.find_connection_file`:
339 339
340 340 .. sourcecode:: bash
341 341
342 342 $> python -c "from IPython.lib.kernel import find_connection_file;\
343 343 print find_connection_file('kernel-12345.json')"
344 344 /home/you/.ipython/profile_default/security/kernel-12345.json
345 345
346 346 And if you are using a particular IPython profile:
347 347
348 348 .. sourcecode:: bash
349 349
350 350 $> python -c "from IPython.lib.kernel import find_connection_file;\
351 351 print find_connection_file('kernel-12345.json', profile='foo')"
352 352 /home/you/.ipython/profile_foo/security/kernel-12345.json
353 353
354 354 You can even launch a standalone kernel, and connect and disconnect Qt Consoles
355 355 from various machines. This lets you keep the same running IPython session
356 356 on your work machine (with matplotlib plots and everything), logging in from home,
357 357 cafΓ©s, etc.::
358 358
359 359 $> ipython kernel
360 360 [IPKernelApp] To connect another client to this kernel, use:
361 361 [IPKernelApp] --existing kernel-12345.json
362 362
363 363 This is actually exactly the same as the subprocess launched by the qtconsole, so
364 364 all the information about connecting to a standalone kernel is identical to that
365 365 of connecting to the kernel attached to a running console.
366 366
367 367 .. _kernel_security:
368 368
369 369 Security
370 370 --------
371 371
372 372 .. warning::
373 373
374 374 Since the ZMQ code currently has no encryption, listening on an
375 375 external-facing IP is dangerous. You are giving any computer that can see
376 376 you on the network the ability to connect to your kernel, and view your traffic.
377 377 Read the rest of this section before listening on external ports
378 378 or running an IPython kernel on a shared machine.
379 379
380 380 By default (for security reasons), the kernel only listens on localhost, so you
381 381 can only connect multiple frontends to the kernel from your local machine. You
382 382 can specify to listen on an external interface by specifying the ``ip``
383 383 argument::
384 384
385 385 $> ipython qtconsole --ip=192.168.1.123
386 386
387 387 If you specify the ip as 0.0.0.0 or '*', that means all interfaces, so any
388 388 computer that can see yours on the network can connect to the kernel.
389 389
390 390 Messages are not encrypted, so users with access to the ports your kernel is using will be
391 391 able to see any output of the kernel. They will **NOT** be able to issue shell commands as
392 392 you due to message signatures, which are enabled by default as of IPython 0.12.
393 393
394 394 .. warning::
395 395
396 396 If you disable message signatures, then any user with access to the ports your
397 397 kernel is listening on can issue arbitrary code as you. **DO NOT** disable message
398 398 signatures unless you have a lot of trust in your environment.
399 399
400 400 The one security feature IPython does provide is protection from unauthorized execution.
401 401 IPython's messaging system will sign messages with HMAC digests using a shared-key. The key
402 402 is never sent over the network, it is only used to generate a unique hash for each message,
403 403 based on its content. When IPython receives a message, it will check that the digest
404 404 matches, and discard the message. You can use any file that only you have access to to
405 405 generate this key, but the default is just to generate a new UUID. You can generate a random
406 406 private key with::
407 407
408 408 # generate 1024b of random data, and store in a file only you can read:
409 409 # (assumes IPYTHONDIR is defined, otherwise use your IPython directory)
410 410 $> python -c "import os; print os.urandom(128).encode('base64')" > $IPYTHONDIR/sessionkey
411 411 $> chmod 600 $IPYTHONDIR/sessionkey
412 412
413 413 The *contents* of this file will be stored in the JSON connection file, so that file
414 414 contains everything you need to connect to and use a kernel.
415 415
416 416 To use this generated key, simply specify the ``Session.keyfile`` configurable
417 417 in :file:`ipython_config.py` or at the command-line, as in::
418 418
419 419 # instruct IPython to sign messages with that key, instead of a new UUID
420 420 $> ipython qtconsole --Session.keyfile=$IPYTHONDIR/sessionkey
421 421
422 422 .. _ssh_tunnels:
423 423
424 424 SSH Tunnels
425 425 -----------
426 426
427 427 Sometimes you want to connect to machines across the internet, or just across
428 428 a LAN that either doesn't permit open ports or you don't trust the other
429 429 machines on the network. To do this, you can use SSH tunnels. SSH tunnels
430 430 are a way to securely forward ports on your local machine to ports on another
431 431 machine, to which you have SSH access.
432 432
433 433 In simple cases, IPython's tools can forward ports over ssh by simply adding the
434 434 ``--ssh=remote`` argument to the usual ``--existing...`` set of flags for connecting
435 435 to a running kernel, after copying the JSON connection file (or its contents) to
436 436 the second computer.
437 437
438 438 .. warning::
439 439
440 440 Using SSH tunnels does *not* increase localhost security. In fact, when
441 441 tunneling from one machine to another *both* machines have open
442 442 ports on localhost available for connections to the kernel.
443 443
444 444 There are two primary models for using SSH tunnels with IPython. The first
445 445 is to have the Kernel listen only on localhost, and connect to it from
446 446 another machine on the same LAN.
447 447
448 448 First, let's start a kernel on machine **worker**, listening only
449 449 on loopback::
450 450
451 451 user@worker $> ipython kernel
452 452 [IPKernelApp] To connect another client to this kernel, use:
453 453 [IPKernelApp] --existing kernel-12345.json
454 454
455 455 In this case, the IP that you would connect
456 456 to would still be 127.0.0.1, but you want to specify the additional ``--ssh`` argument
457 457 with the hostname of the kernel (in this example, it's 'worker')::
458 458
459 459 user@client $> ipython qtconsole --ssh=worker --existing /path/to/kernel-12345.json
460 460
461 461 Which will write a new connection file with the forwarded ports, so you can reuse them::
462 462
463 463 [IPythonQtConsoleApp] To connect another client via this tunnel, use:
464 464 [IPythonQtConsoleApp] --existing kernel-12345-ssh.json
465 465
466 466 Note again that this opens ports on the *client* machine that point to your kernel.
467 467
468 468 .. note::
469 469
470 470 the ssh argument is simply passed to openssh, so it can be fully specified ``user@host:port``
471 471 but it will also respect your aliases, etc. in :file:`.ssh/config` if you have any.
472 472
473 473 The second pattern is for connecting to a machine behind a firewall across the internet
474 474 (or otherwise wide network). This time, we have a machine **login** that you have ssh access
475 475 to, which can see **kernel**, but **client** is on another network. The important difference
476 476 now is that **client** can see **login**, but *not* **worker**. So we need to forward ports from
477 477 client to worker *via* login. This means that the kernel must be started listening
478 478 on external interfaces, so that its ports are visible to `login`::
479 479
480 480 user@worker $> ipython kernel --ip=0.0.0.0
481 481 [IPKernelApp] To connect another client to this kernel, use:
482 482 [IPKernelApp] --existing kernel-12345.json
483 483
484 484 Which we can connect to from the client with::
485 485
486 486 user@client $> ipython qtconsole --ssh=login --ip=192.168.1.123 --existing /path/to/kernel-12345.json
487 487
488 488 .. note::
489 489
490 490 The IP here is the address of worker as seen from *login*, and need only be specified if
491 491 the kernel used the ambiguous 0.0.0.0 (all interfaces) address. If it had used
492 492 192.168.1.123 to start with, it would not be needed.
493 493
494 494
495 495 Manual SSH tunnels
496 496 ------------------
497 497
498 498 It's possible that IPython's ssh helper functions won't work for you, for various
499 499 reasons. You can still connect to remote machines, as long as you set up the tunnels
500 500 yourself. The basic format of forwarding a local port to a remote one is::
501 501
502 502 [client] $> ssh <server> <localport>:<remoteip>:<remoteport> -f -N
503 503
504 504 This will forward local connections to **localport** on client to **remoteip:remoteport**
505 505 *via* **server**. Note that remoteip is interpreted relative to *server*, not the client.
506 506 So if you have direct ssh access to the machine to which you want to forward connections,
507 507 then the server *is* the remote machine, and remoteip should be server's IP as seen from the
508 508 server itself, i.e. 127.0.0.1. Thus, to forward local port 12345 to remote port 54321 on
509 509 a machine you can see, do::
510 510
511 511 [client] $> ssh machine 12345:127.0.0.1:54321 -f -N
512 512
513 513 But if your target is actually on a LAN at 192.168.1.123, behind another machine called **login**,
514 514 then you would do::
515 515
516 516 [client] $> ssh login 12345:192.168.1.16:54321 -f -N
517 517
518 518 The ``-f -N`` on the end are flags that tell ssh to run in the background,
519 519 and don't actually run any commands beyond creating the tunnel.
520 520
521 521 .. seealso::
522 522
523 523 A short discussion of ssh tunnels: http://www.revsys.com/writings/quicktips/ssh-tunnel.html
524 524
525 525
526 526
527 527 Stopping Kernels and Consoles
528 528 *****************************
529 529
530 530 Since there can be many consoles per kernel, the shutdown mechanism and dialog
531 531 are probably more complicated than you are used to. Since you don't always want
532 532 to shutdown a kernel when you close a window, you are given the option to just
533 533 close the console window or also close the Kernel and *all other windows*. Note
534 534 that this only refers to all other *local* windows, as remote Consoles are not
535 535 allowed to shutdown the kernel, and shutdowns do not close Remote consoles (to
536 536 allow for saving, etc.).
537 537
538 538 Rules:
539 539
540 540 * Restarting the kernel automatically clears all *local* Consoles, and prompts remote
541 541 Consoles about the reset.
542 542 * Shutdown closes all *local* Consoles, and notifies remotes that
543 543 the Kernel has been shutdown.
544 544 * Remote Consoles may not restart or shutdown the kernel.
545 545
546 546 Qt and the QtConsole
547 547 ====================
548 548
549 549 An important part of working with the QtConsole when you are writing your own
550 550 Qt code is to remember that user code (in the kernel) is *not* in the same
551 551 process as the frontend. This means that there is not necessarily any Qt code
552 552 running in the kernel, and under most normal circumstances there isn't. If,
553 553 however, you specify ``--matplotlib qt`` at the command-line, then there *will* be a
554 554 :class:`QCoreApplication` instance running in the kernel process along with
555 555 user-code. To get a reference to this application, do:
556 556
557 557 .. sourcecode:: python
558 558
559 559 from PyQt4 import QtCore
560 560 app = QtCore.QCoreApplication.instance()
561 561 # app will be None if there is no such instance
562 562
563 563 A common problem listed in the PyQt4 Gotchas_ is the fact that Python's garbage
564 564 collection will destroy Qt objects (Windows, etc.) once there is no longer a
565 565 Python reference to them, so you have to hold on to them. For instance, in:
566 566
567 567 .. sourcecode:: python
568 568
569 569 def make_window():
570 570 win = QtGui.QMainWindow()
571 571
572 572 def make_and_return_window():
573 573 win = QtGui.QMainWindow()
574 574 return win
575 575
576 576 :func:`make_window` will never draw a window, because garbage collection will
577 577 destroy it before it is drawn, whereas :func:`make_and_return_window` lets the
578 578 caller decide when the window object should be destroyed. If, as a developer,
579 579 you know that you always want your objects to last as long as the process, you
580 580 can attach them to the QApplication instance itself:
581 581
582 582 .. sourcecode:: python
583 583
584 584 # do this just once:
585 585 app = QtCore.QCoreApplication.instance()
586 586 app.references = set()
587 587 # then when you create Windows, add them to the set
588 588 def make_window():
589 589 win = QtGui.QMainWindow()
590 590 app.references.add(win)
591 591
592 592 Now the QApplication itself holds a reference to ``win``, so it will never be
593 593 garbage collected until the application itself is destroyed.
594 594
595 595 .. _Gotchas: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html#garbage-collection
596 596
597 Embedding the QtConsole in a Qt application
598 *******************************************
599
600 In order to make the QtConsole available to an external Qt GUI application (just as
601 :func:`IPython.embed` enables one to embed a terminal session of IPython in a
602 command-line application), there are a few options:
603
604 * First start IPython, and then start the external Qt application from IPython,
605 as described above. Effectively, this embeds your application in IPython
606 rather than the other way round.
607
608 * Use :class:`IPython.qt.console.rich_ipython_widget.RichIPythonWidget` in your
609 Qt application. This will embed the console widget in your GUI and start the
610 kernel in a separate process, so code typed into the console cannot access
611 objects in your application.
612
613 * Start a standard IPython kernel in the process of the external Qt
614 application. See :file:`examples/lib/ipkernel_qtapp.py` for an example. Due
615 to IPython's two-process model, the QtConsole itself will live in another
616 process with its own QApplication, and thus cannot be embedded in the main
617 GUI.
618
619 * Start a special IPython kernel, the
620 :class:`IPython.kernel.inprocess.ipkernel.InProcessKernel`, that allows a
621 QtConsole in the same process. See :file:`examples/inprocess/embedded_qtconsole.py`
622 for an example. While the QtConsole can now be embedded in the main GUI, one
623 cannot connect to the kernel from other consoles as there are no real ZMQ
624 sockets anymore.
625
597 626 Regressions
598 627 ===========
599 628
600 629 There are some features, where the qt console lags behind the Terminal
601 630 frontend:
602 631
603 632 * !cmd input: Due to our use of pexpect, we cannot pass input to subprocesses
604 633 launched using the '!' escape, so you should never call a command that
605 634 requires interactive input. For such cases, use the terminal IPython. This
606 635 will not be fixed, as abandoning pexpect would significantly degrade the
607 636 console experience.
608 637
609 638 .. _PyQt: http://www.riverbankcomputing.co.uk/software/pyqt/download
610 639 .. _pygments: http://pygments.org/
General Comments 0
You need to be logged in to leave comments. Login now