##// END OF EJS Templates
Merge pull request #10881 from JeremySikes73/doc...
Thomas Kluyver -
r24030:0920f3a1 merge
parent child Browse files
Show More
@@ -1,99 +1,99 b''
1 1 .. _events:
2 2 .. _callbacks:
3 3
4 4 ==============
5 5 IPython Events
6 6 ==============
7 7
8 8 Extension code can register callbacks functions which will be called on specific
9 9 events within the IPython code. You can see the current list of available
10 10 callbacks, and the parameters that will be passed with each, in the callback
11 prototype functions defined in :mod:`IPython.core.callbacks`.
11 prototype functions defined in :mod:`IPython.core.events`.
12 12
13 13 To register callbacks, use :meth:`IPython.core.events.EventManager.register`.
14 14 For example::
15 15
16 16 class VarWatcher(object):
17 17 def __init__(self, ip):
18 18 self.shell = ip
19 19 self.last_x = None
20 20
21 21 def pre_execute(self):
22 22 self.last_x = self.shell.user_ns.get('x', None)
23 23
24 24 def pre_run_cell(self, info):
25 25 print('Cell code: "%s"' % info.raw_cell)
26 26
27 27 def post_execute(self):
28 28 if self.shell.user_ns.get('x', None) != self.last_x:
29 29 print("x changed!")
30 30
31 31 def post_run_cell(self, result):
32 32 print('Cell code: "%s"' % result.info.raw_cell)
33 33 if result.error_before_exec:
34 34 print('Error before execution: %s' % result.error_before_exec)
35 35
36 36 def load_ipython_extension(ip):
37 37 vw = VarWatcher(ip)
38 38 ip.events.register('pre_execute', vw.pre_execute)
39 39 ip.events.register('pre_run_cell', vw.pre_run_cell)
40 40 ip.events.register('post_execute', vw.post_execute)
41 41 ip.events.register('post_run_cell', vw.post_run_cell)
42 42
43 43
44 44 Events
45 45 ======
46 46
47 47 These are the events IPython will emit. Callbacks will be passed no arguments, unless otherwise specified.
48 48
49 49 shell_initialized
50 50 -----------------
51 51
52 52 .. code-block:: python
53 53
54 54 def shell_initialized(ipython):
55 55 ...
56 56
57 57 This event is triggered only once, at the end of setting up IPython.
58 58 Extensions registered to load by default as part of configuration can use this to execute code to finalize setup.
59 59 Callbacks will be passed the InteractiveShell instance.
60 60
61 61 pre_run_cell
62 62 ------------
63 63
64 64 ``pre_run_cell`` fires prior to interactive execution (e.g. a cell in a notebook).
65 65 It can be used to note the state prior to execution, and keep track of changes.
66 66 An object containing information used for the code execution is provided as an argument.
67 67
68 68 pre_execute
69 69 -----------
70 70
71 71 ``pre_execute`` is like ``pre_run_cell``, but is triggered prior to *any* execution.
72 72 Sometimes code can be executed by libraries, etc. which
73 73 skipping the history/display mechanisms, in which cases ``pre_run_cell`` will not fire.
74 74
75 75 post_run_cell
76 76 -------------
77 77
78 78 ``post_run_cell`` runs after interactive execution (e.g. a cell in a notebook).
79 79 It can be used to cleanup or notify or perform operations on any side effects produced during execution.
80 80 For instance, the inline matplotlib backend uses this event to display any figures created but not explicitly displayed during the course of the cell.
81 81 The object which will be returned as the execution result is provided as an
82 82 argument.
83 83
84 84 post_execute
85 85 ------------
86 86
87 87 The same as ``pre_execute``, ``post_execute`` is like ``post_run_cell``,
88 88 but fires for *all* executions, not just interactive ones.
89 89
90 90
91 91 .. seealso::
92 92
93 93 Module :mod:`IPython.core.hooks`
94 94 The older 'hooks' system allows end users to customise some parts of
95 95 IPython's behaviour.
96 96
97 97 :doc:`inputtransforms`
98 98 By registering input transformers that don't change code, you can monitor
99 99 what is being executed.
@@ -1,95 +1,108 b''
1 1 ================================
2 2 Integrating with GUI event loops
3 3 ================================
4 4
5 5 When the user types ``%gui qt``, IPython integrates itself with the Qt event
6 6 loop, so you can use both a GUI and an interactive prompt together. IPython
7 7 supports a number of common GUI toolkits, but from IPython 3.0, it is possible
8 8 to integrate other event loops without modifying IPython itself.
9 9
10 Terminal IPython handles event loops very differently from the IPython kernel,
11 so different steps are needed to integrate with each.
10 Supported event loops include ``qt4``, ``qt5``, ``gtk2``, ``gtk3``, ``wx``,
11 ``osx`` and ``tk``. Make sure the event loop you specify matches the GUI
12 toolkit used by your own code.
12 13
13 Event loops in the terminal
14 ---------------------------
14 To make IPython GUI event loop integration occur automatically at every
15 startup, set the ``c.InteractiveShellApp.gui`` configuration key in your
16 IPython profile (see :ref:`setting_config`).
17
18 If the event loop you use is supported by IPython, turning on event loop
19 integration follows the steps just described whether you use Terminal IPython
20 or an IPython kernel.
21
22 However, the way Terminal IPython handles event loops is very different from
23 the way IPython kernel does, so if you need to integrate with a new kind of
24 event loop, different steps are needed to integrate with each.
25
26 Integrating with a new event loop in the terminal
27 -------------------------------------------------
15 28
16 29 .. versionchanged:: 5.0
17 30
18 31 There is a new API for event loop integration using prompt_toolkit.
19 32
20 33 In the terminal, IPython uses prompt_toolkit to prompt the user for input.
21 34 prompt_toolkit provides hooks to integrate with an external event loop.
22 35
23 36 To integrate an event loop, define a function which runs the GUI event loop
24 37 until there is input waiting for prompt_toolkit to process. There are two ways
25 38 to detect this condition::
26 39
27 40 # Polling for input.
28 41 def inputhook(context):
29 42 while not context.input_is_ready():
30 43 # Replace this with the appropriate call for the event loop:
31 44 iterate_loop_once()
32 45
33 46 # Using a file descriptor to notify the event loop to stop.
34 47 def inputhook2(context):
35 48 fd = context.fileno()
36 49 # Replace the functions below with those for the event loop.
37 50 add_file_reader(fd, callback=stop_the_loop)
38 51 run_the_loop()
39 52
40 53 Once you have defined this function, register it with IPython:
41 54
42 55 .. currentmodule:: IPython.terminal.pt_inputhooks
43 56
44 57 .. function:: register(name, inputhook)
45 58
46 59 Register the function *inputhook* as the event loop integration for the
47 60 GUI *name*. If ``name='foo'``, then the user can enable this integration
48 61 by running ``%gui foo``.
49 62
50 63
51 Event loops in the kernel
52 -------------------------
64 Integrating with a new event loop in the kernel
65 -----------------------------------------------
53 66
54 67 The kernel runs its own event loop, so it's simpler to integrate with others.
55 68 IPython allows the other event loop to take control, but it must call
56 69 :meth:`IPython.kernel.zmq.kernelbase.Kernel.do_one_iteration` periodically.
57 70
58 71 To integrate with this, write a function that takes a single argument,
59 72 the IPython kernel instance, arranges for your event loop to call
60 73 ``kernel.do_one_iteration()`` at least every ``kernel._poll_interval`` seconds,
61 74 and starts the event loop.
62 75
63 76 Decorate this function with :func:`IPython.kernel.zmq.eventloops.register_integration`,
64 77 passing in the names you wish to register it for. Here is a slightly simplified
65 78 version of the Tkinter integration already included in IPython::
66 79
67 80 @register_integration('tk')
68 81 def loop_tk(kernel):
69 82 """Start a kernel with the Tk event loop."""
70 83 from tkinter import Tk
71 84
72 85 # Tk uses milliseconds
73 86 poll_interval = int(1000*kernel._poll_interval)
74 87 # For Tkinter, we create a Tk object and call its withdraw method.
75 88 class Timer(object):
76 89 def __init__(self, func):
77 90 self.app = Tk()
78 91 self.app.withdraw()
79 92 self.func = func
80 93
81 94 def on_timer(self):
82 95 self.func()
83 96 self.app.after(poll_interval, self.on_timer)
84 97
85 98 def start(self):
86 99 self.on_timer() # Call it once to get things going.
87 100 self.app.mainloop()
88 101
89 102 kernel.timer = Timer(kernel.do_one_iteration)
90 103 kernel.timer.start()
91 104
92 105 Some event loops can go one better, and integrate checking for messages on the
93 106 kernel's ZMQ sockets, making the kernel more responsive than plain polling. How
94 107 to do this is outside the scope of this document; if you are interested, look at
95 108 the integration with Qt in :mod:`IPython.kernel.zmq.eventloops`.
General Comments 0
You need to be logged in to leave comments. Login now