##// END OF EJS Templates
Merge pull request #1787 from punchagan/minor-doc-fix...
Jonathan March -
r7068:e0e173d6 merge
parent child Browse files
Show More
@@ -1,609 +1,604 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 262
263 263 Fonts
264 264 =====
265 265
266 266 The QtConsole has configurable via the ConsoleWidget. To change these, set the
267 267 ``font_family`` or ``font_size`` traits of the ConsoleWidget. For instance, to
268 268 use 9pt Anonymous Pro::
269 269
270 270 $> ipython qtconsole --ConsoleWidget.font_family="Anonymous Pro" --ConsoleWidget.font_size=9
271 271
272 272 Process Management
273 273 ==================
274 274
275 275 With the two-process ZMQ model, the frontend does not block input during
276 276 execution. This means that actions can be taken by the frontend while the
277 277 Kernel is executing, or even after it crashes. The most basic such command is
278 278 via 'Ctrl-.', which restarts the kernel. This can be done in the middle of a
279 279 blocking execution. The frontend can also know, via a heartbeat mechanism, that
280 280 the kernel has died. This means that the frontend can safely restart the
281 281 kernel.
282 282
283 283 .. _multiple_consoles:
284 284
285 285 Multiple Consoles
286 286 *****************
287 287
288 288 Since the Kernel listens on the network, multiple frontends can connect to it.
289 289 These do not have to all be qt frontends - any IPython frontend can connect and
290 290 run code. When you start ipython qtconsole, there will be an output line,
291 291 like::
292 292
293 293 [IPKernelApp] To connect another client to this kernel, use:
294 294 [IPKernelApp] --existing kernel-12345.json
295 295
296 296 Other frontends can connect to your kernel, and share in the execution. This is
297 297 great for collaboration. The ``--existing`` flag means connect to a kernel
298 298 that already exists. Starting other consoles
299 299 with that flag will not try to start their own kernel, but rather connect to
300 300 yours. :file:`kernel-12345.json` is a small JSON file with the ip, port, and
301 301 authentication information necessary to connect to your kernel. By default, this file
302 302 will be in your default profile's security directory. If it is somewhere else,
303 303 the output line will print the full path of the connection file, rather than
304 304 just its filename.
305 305
306 306 If you need to find the connection info to send, and don't know where your connection file
307 307 lives, there are a couple of ways to get it. If you are already running an IPython console
308 308 connected to the kernel, you can use the ``%connect_info`` magic to display the information
309 309 necessary to connect another frontend to the kernel.
310 310
311 311 .. sourcecode:: ipython
312 312
313 313 In [2]: %connect_info
314 314 {
315 315 "stdin_port":50255,
316 316 "ip":"127.0.0.1",
317 317 "hb_port":50256,
318 318 "key":"70be6f0f-1564-4218-8cda-31be40a4d6aa",
319 319 "shell_port":50253,
320 320 "iopub_port":50254
321 321 }
322 322
323 323 Paste the above JSON into a file, and connect with:
324 324 $> ipython <app> --existing <file>
325 325 or, if you are local, you can connect with just:
326 326 $> ipython <app> --existing kernel-12345.json
327 327 or even just:
328 328 $> ipython <app> --existing
329 329 if this is the most recent IPython session you have started.
330 330
331 331 Otherwise, you can find a connection file by name (and optionally profile) with
332 332 :func:`IPython.lib.kernel.find_connection_file`:
333 333
334 334 .. sourcecode:: bash
335 335
336 336 $> python -c "from IPython.lib.kernel import find_connection_file;\
337 337 print find_connection_file('kernel-12345.json')"
338 338 /home/you/.ipython/profile_default/security/kernel-12345.json
339 339
340 340 And if you are using a particular IPython profile:
341 341
342 342 .. sourcecode:: bash
343 343
344 344 $> python -c "from IPython.lib.kernel import find_connection_file;\
345 345 print find_connection_file('kernel-12345.json', profile='foo')"
346 346 /home/you/.ipython/profile_foo/security/kernel-12345.json
347 347
348 348 You can even launch a standalone kernel, and connect and disconnect Qt Consoles
349 349 from various machines. This lets you keep the same running IPython session
350 350 on your work machine (with matplotlib plots and everything), logging in from home,
351 351 cafΓ©s, etc.::
352 352
353 353 $> ipython kernel
354 354 [IPKernelApp] To connect another client to this kernel, use:
355 355 [IPKernelApp] --existing kernel-12345.json
356 356
357 357 This is actually exactly the same as the subprocess launched by the qtconsole, so
358 358 all the information about connecting to a standalone kernel is identical to that
359 359 of connecting to the kernel attached to a running console.
360 360
361 361 .. _kernel_security:
362 362
363 363 Security
364 364 --------
365 365
366 366 .. warning::
367 367
368 368 Since the ZMQ code currently has no encryption, listening on an
369 369 external-facing IP is dangerous. You are giving any computer that can see
370 370 you on the network the ability to connect to your kernel, and view your traffic.
371 371 Read the rest of this section before listening on external ports
372 372 or running an IPython kernel on a shared machine.
373 373
374 374 By default (for security reasons), the kernel only listens on localhost, so you
375 375 can only connect multiple frontends to the kernel from your local machine. You
376 376 can specify to listen on an external interface by specifying the ``ip``
377 377 argument::
378 378
379 379 $> ipython qtconsole --ip=192.168.1.123
380 380
381 381 If you specify the ip as 0.0.0.0 or '*', that means all interfaces, so any
382 382 computer that can see yours on the network can connect to the kernel.
383 383
384 384 Messages are not encrypted, so users with access to the ports your kernel is using will be
385 385 able to see any output of the kernel. They will **NOT** be able to issue shell commands as
386 386 you due to message signatures, which are enabled by default as of IPython 0.12.
387 387
388 388 .. warning::
389 389
390 390 If you disable message signatures, then any user with access to the ports your
391 391 kernel is listening on can issue arbitrary code as you. **DO NOT** disable message
392 392 signatures unless you have a lot of trust in your environment.
393 393
394 394 The one security feature IPython does provide is protection from unauthorized execution.
395 395 IPython's messaging system will sign messages with HMAC digests using a shared-key. The key
396 396 is never sent over the network, it is only used to generate a unique hash for each message,
397 397 based on its content. When IPython receives a message, it will check that the digest
398 398 matches, and discard the message. You can use any file that only you have access to to
399 399 generate this key, but the default is just to generate a new UUID. You can generate a random
400 400 private key with::
401 401
402 402 # generate 1024b of random data, and store in a file only you can read:
403 403 # (assumes IPYTHONDIR is defined, otherwise use your IPython directory)
404 404 $> python -c "import os; print os.urandom(128).encode('base64')" > $IPYTHONDIR/sessionkey
405 405 $> chmod 600 $IPYTHONDIR/sessionkey
406 406
407 407 The *contents* of this file will be stored in the JSON connection file, so that file
408 408 contains everything you need to connect to and use a kernel.
409 409
410 410 To use this generated key, simply specify the ``Session.keyfile`` configurable
411 411 in :file:`ipython_config.py` or at the command-line, as in::
412 412
413 413 # instruct IPython to sign messages with that key, instead of a new UUID
414 414 $> ipython qtconsole --Session.keyfile=$IPYTHONDIR/sessionkey
415 415
416 416 .. _ssh_tunnels:
417 417
418 418 SSH Tunnels
419 419 -----------
420 420
421 421 Sometimes you want to connect to machines across the internet, or just across
422 422 a LAN that either doesn't permit open ports or you don't trust the other
423 423 machines on the network. To do this, you can use SSH tunnels. SSH tunnels
424 424 are a way to securely forward ports on your local machine to ports on another
425 425 machine, to which you have SSH access.
426 426
427 427 In simple cases, IPython's tools can forward ports over ssh by simply adding the
428 428 ``--ssh=remote`` argument to the usual ``--existing...`` set of flags for connecting
429 429 to a running kernel, after copying the JSON connection file (or its contents) to
430 430 the second computer.
431 431
432 432 .. warning::
433 433
434 434 Using SSH tunnels does *not* increase localhost security. In fact, when
435 435 tunneling from one machine to another *both* machines have open
436 436 ports on localhost available for connections to the kernel.
437 437
438 438 There are two primary models for using SSH tunnels with IPython. The first
439 439 is to have the Kernel listen only on localhost, and connect to it from
440 440 another machine on the same LAN.
441 441
442 442 First, let's start a kernel on machine **worker**, listening only
443 443 on loopback::
444 444
445 445 user@worker $> ipython kernel
446 446 [IPKernelApp] To connect another client to this kernel, use:
447 447 [IPKernelApp] --existing kernel-12345.json
448 448
449 449 In this case, the IP that you would connect
450 450 to would still be 127.0.0.1, but you want to specify the additional ``--ssh`` argument
451 451 with the hostname of the kernel (in this example, it's 'worker')::
452 452
453 453 user@client $> ipython qtconsole --ssh=worker --existing /path/to/kernel-12345.json
454 454
455 455 Which will write a new connection file with the forwarded ports, so you can reuse them::
456 456
457 457 [IPythonQtConsoleApp] To connect another client via this tunnel, use:
458 458 [IPythonQtConsoleApp] --existing kernel-12345-ssh.json
459 459
460 460 Note again that this opens ports on the *client* machine that point to your kernel.
461 461
462 462 .. note::
463 463
464 464 the ssh argument is simply passed to openssh, so it can be fully specified ``user@host:port``
465 465 but it will also respect your aliases, etc. in :file:`.ssh/config` if you have any.
466 466
467 467 The second pattern is for connecting to a machine behind a firewall across the internet
468 468 (or otherwise wide network). This time, we have a machine **login** that you have ssh access
469 469 to, which can see **kernel**, but **client** is on another network. The important difference
470 470 now is that **client** can see **login**, but *not* **worker**. So we need to forward ports from
471 471 client to worker *via* login. This means that the kernel must be started listening
472 472 on external interfaces, so that its ports are visible to `login`::
473 473
474 474 user@worker $> ipython kernel --ip=0.0.0.0
475 475 [IPKernelApp] To connect another client to this kernel, use:
476 476 [IPKernelApp] --existing kernel-12345.json
477 477
478 478 Which we can connect to from the client with::
479 479
480 480 user@client $> ipython qtconsole --ssh=login --ip=192.168.1.123 --existing /path/to/kernel-12345.json
481 481
482 482 .. note::
483 483
484 484 The IP here is the address of worker as seen from *login*, and need only be specified if
485 485 the kernel used the ambiguous 0.0.0.0 (all interfaces) address. If it had used
486 486 192.168.1.123 to start with, it would not be needed.
487 487
488 488
489 489 Manual SSH tunnels
490 490 ------------------
491 491
492 492 It's possible that IPython's ssh helper functions won't work for you, for various
493 493 reasons. You can still connect to remote machines, as long as you set up the tunnels
494 494 yourself. The basic format of forwarding a local port to a remote one is::
495 495
496 496 [client] $> ssh <server> <localport>:<remoteip>:<remoteport> -f -N
497 497
498 498 This will forward local connections to **localport** on client to **remoteip:remoteport**
499 499 *via* **server**. Note that remoteip is interpreted relative to *server*, not the client.
500 500 So if you have direct ssh access to the machine to which you want to forward connections,
501 501 then the server *is* the remote machine, and remoteip should be server's IP as seen from the
502 502 server itself, i.e. 127.0.0.1. Thus, to forward local port 12345 to remote port 54321 on
503 503 a machine you can see, do::
504 504
505 505 [client] $> ssh machine 12345:127.0.0.1:54321 -f -N
506 506
507 507 But if your target is actually on a LAN at 192.168.1.123, behind another machine called **login**,
508 508 then you would do::
509 509
510 510 [client] $> ssh login 12345:192.168.1.16:54321 -f -N
511 511
512 512 The ``-f -N`` on the end are flags that tell ssh to run in the background,
513 513 and don't actually run any commands beyond creating the tunnel.
514 514
515 515 .. seealso::
516 516
517 517 A short discussion of ssh tunnels: http://www.revsys.com/writings/quicktips/ssh-tunnel.html
518 518
519 519
520 520
521 521 Stopping Kernels and Consoles
522 522 *****************************
523 523
524 524 Since there can be many consoles per kernel, the shutdown mechanism and dialog
525 525 are probably more complicated than you are used to. Since you don't always want
526 526 to shutdown a kernel when you close a window, you are given the option to just
527 527 close the console window or also close the Kernel and *all other windows*. Note
528 528 that this only refers to all other *local* windows, as remote Consoles are not
529 529 allowed to shutdown the kernel, and shutdowns do not close Remote consoles (to
530 530 allow for saving, etc.).
531 531
532 532 Rules:
533 533
534 534 * Restarting the kernel automatically clears all *local* Consoles, and prompts remote
535 535 Consoles about the reset.
536 536 * Shutdown closes all *local* Consoles, and notifies remotes that
537 537 the Kernel has been shutdown.
538 538 * Remote Consoles may not restart or shutdown the kernel.
539 539
540 540 Qt and the QtConsole
541 541 ====================
542 542
543 543 An important part of working with the QtConsole when you are writing your own
544 544 Qt code is to remember that user code (in the kernel) is *not* in the same
545 545 process as the frontend. This means that there is not necessarily any Qt code
546 546 running in the kernel, and under most normal circumstances there isn't. If,
547 547 however, you specify ``--pylab=qt`` at the command-line, then there *will* be a
548 548 :class:`QCoreApplication` instance running in the kernel process along with
549 549 user-code. To get a reference to this application, do:
550 550
551 551 .. sourcecode:: python
552 552
553 553 from PyQt4 import QtCore
554 554 app = QtCore.QCoreApplication.instance()
555 555 # app will be None if there is no such instance
556 556
557 557 A common problem listed in the PyQt4 Gotchas_ is the fact that Python's garbage
558 558 collection will destroy Qt objects (Windows, etc.) once there is no longer a
559 559 Python reference to them, so you have to hold on to them. For instance, in:
560 560
561 561 .. sourcecode:: python
562 562
563 563 def make_window():
564 564 win = QtGui.QMainWindow()
565 565
566 566 def make_and_return_window():
567 567 win = QtGui.QMainWindow()
568 568 return win
569 569
570 570 :func:`make_window` will never draw a window, because garbage collection will
571 571 destroy it before it is drawn, whereas :func:`make_and_return_window` lets the
572 572 caller decide when the window object should be destroyed. If, as a developer,
573 573 you know that you always want your objects to last as long as the process, you
574 574 can attach them to the QApplication instance itself:
575 575
576 576 .. sourcecode:: python
577 577
578 578 # do this just once:
579 579 app = QtCore.QCoreApplication.instance()
580 580 app.references = set()
581 581 # then when you create Windows, add them to the set
582 582 def make_window():
583 583 win = QtGui.QMainWindow()
584 584 app.references.add(win)
585 585
586 586 Now the QApplication itself holds a reference to ``win``, so it will never be
587 587 garbage collected until the application itself is destroyed.
588 588
589 589 .. _Gotchas: http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/gotchas.html#garbage-collection
590 590
591 591 Regressions
592 592 ===========
593 593
594 594 There are some features, where the qt console lags behind the Terminal
595 595 frontend:
596 596
597 597 * !cmd input: Due to our use of pexpect, we cannot pass input to subprocesses
598 598 launched using the '!' escape, so you should never call a command that
599 599 requires interactive input. For such cases, use the terminal IPython. This
600 600 will not be fixed, as abandoning pexpect would significantly degrade the
601 601 console experience.
602 602
603 * Use of ``\b`` and ``\r`` characters in the console: these are control
604 characters that allow the cursor to move backwards on a line, and are used to
605 display things like in-place progress bars in a terminal. We currently do
606 not support this, but it is being tracked as issue :ghissue:`629`.
607
608 603 .. _PyQt: http://www.riverbankcomputing.co.uk/software/pyqt/download
609 604 .. _pygments: http://pygments.org/
General Comments 0
You need to be logged in to leave comments. Login now