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