##// END OF EJS Templates
General work on inputhook and the docs....
Brian Granger -
Show More
@@ -3542,6 +3542,8 b' Defaulting color scheme to \'NoColor\'"""'
3542 3542 def magic_gui(self, parameter_s=''):
3543 3543 """Enable or disable IPython GUI event loop integration.
3544 3544
3545 %gui [-a] [GUINAME]
3546
3545 3547 This magic replaces IPython's threaded shells that were activated
3546 3548 using the (pylab/wthread/etc.) command line flags. GUI toolkits
3547 3549 can now be enabled, disabled and swtiched at runtime and keyboard
@@ -24,7 +24,11 b' import sys'
24 24
25 25
26 26 class InputHookManager(object):
27 """Manage PyOS_InputHook for different GUI toolkits."""
27 """Manage PyOS_InputHook for different GUI toolkits.
28
29 This class installs various hooks under ``PyOSInputHook`` to handle
30 GUI event loop integration.
31 """
28 32
29 33 def __init__(self):
30 34 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
@@ -34,6 +38,7 b' class InputHookManager(object):'
34 38 self._callback_pyfunctype = None
35 39 self._callback = None
36 40 self._installed = False
41 self._current_gui = None
37 42
38 43 def get_pyos_inputhook(self):
39 44 """Return the current PyOS_InputHook as a ctypes.c_void_p.
@@ -68,7 +73,14 b' class InputHookManager(object):'
68 73
69 74 def enable_wx(self, app=False):
70 75 """Enable event loop integration with wxPython.
71
76
77 Parameters
78 ----------
79 app : bool
80 Create a running application object or not.
81
82 Notes
83 -----
72 84 This methods sets the PyOS_InputHook for wxPython, which allows
73 85 the wxPython to integrate with terminal based applications like
74 86 IPython.
@@ -86,6 +98,7 b' class InputHookManager(object):'
86 98 """
87 99 from IPython.lib.inputhookwx import inputhook_wx
88 100 self.set_inputhook(inputhook_wx)
101 self._current_gui = 'wx'
89 102 if app:
90 103 import wx
91 104 app = wx.App(redirect=False, clearSigInt=False)
@@ -101,6 +114,13 b' class InputHookManager(object):'
101 114 def enable_qt4(self, app=False):
102 115 """Enable event loop integration with PyQt4.
103 116
117 Parameters
118 ----------
119 app : bool
120 Create a running application object or not.
121
122 Notes
123 -----
104 124 This methods sets the PyOS_InputHook for wxPython, which allows
105 125 the PyQt4 to integrate with terminal based applications like
106 126 IPython.
@@ -118,6 +138,7 b' class InputHookManager(object):'
118 138 QtCore.pyqtRestoreInputHook()
119 139 except AttributeError:
120 140 pass
141 self._current_gui = 'qt4'
121 142 if app:
122 143 from PyQt4 import QtGui
123 144 app = QtGui.QApplication(sys.argv)
@@ -132,7 +153,14 b' class InputHookManager(object):'
132 153
133 154 def enable_gtk(self, app=False):
134 155 """Enable event loop integration with PyGTK.
135
156
157 Parameters
158 ----------
159 app : bool
160 Create a running application object or not.
161
162 Notes
163 -----
136 164 This methods sets the PyOS_InputHook for PyGTK, which allows
137 165 the PyGTK to integrate with terminal based applications like
138 166 IPython.
@@ -144,6 +172,7 b' class InputHookManager(object):'
144 172 import gtk
145 173 try:
146 174 gtk.set_interactive(True)
175 self._current_gui = 'gtk'
147 176 except AttributeError:
148 177 # For older versions of gtk, use our own ctypes version
149 178 from IPython.lib.inputhookgtk import inputhook_gtk
@@ -157,8 +186,19 b' class InputHookManager(object):'
157 186 self.clear_inputhook()
158 187
159 188 def enable_tk(self, app=False):
160 # Creating a Tkinter.Tk object sets PyOS_InputHook()
161 pass
189 """Enable event loop integration with Tk.
190
191 Parameters
192 ----------
193 app : bool
194 Create a running application object or not.
195
196 Notes
197 -----
198 Currently this is a no-op as creating a :class:`Tkinter.Tk` object
199 sets ``PyOS_InputHook``.
200 """
201 self._current_gui = 'tk'
162 202
163 203 def disable_tk(self):
164 204 """Disable event loop integration with Tkinter.
@@ -167,6 +207,10 b' class InputHookManager(object):'
167 207 """
168 208 self.clear_inputhook()
169 209
210 def current_gui(self):
211 """Return a string indicating the currently active GUI or None."""
212 return self._current_gui
213
170 214 inputhook_manager = InputHookManager()
171 215
172 216 enable_wx = inputhook_manager.enable_wx
@@ -178,4 +222,5 b' disable_gtk = inputhook_manager.disable_gtk'
178 222 enable_tk = inputhook_manager.enable_tk
179 223 disable_tk = inputhook_manager.disable_tk
180 224 clear_inputhook = inputhook_manager.clear_inputhook
181 set_inputhook = inputhook_manager.set_inputhook No newline at end of file
225 set_inputhook = inputhook_manager.set_inputhook
226 current_gui = inputhook_manager.current_gui No newline at end of file
@@ -20,8 +20,10 b" if __name__ == '__main__':"
20 20 r'\.extensions',
21 21 r'\.kernel.config',
22 22 r'\.attic',
23 r'\.quarantine',
24 r'\.deathrow'
23 25 ]
24 docwriter.module_skip_patterns += [ r'\.FakeModule',
26 docwriter.module_skip_patterns += [ r'\.core.fakemodule',
25 27 r'\.cocoa',
26 28 r'\.ipdoctest',
27 29 r'\.Gnuplot',
@@ -132,7 +132,8 b' using the :command:`iptest` command (which is basically a customized version of'
132 132 $ iptest
133 133
134 134 The :command:`iptest` command will also pick up and run any tests you have
135 written. See :ref:`_devel_testing` for further details on the testing system.
135 written. See :ref:`testing documentation <devel_testing>` for further details
136 on the testing system.
136 137
137 138
138 139 Post your branch and request a code review
@@ -170,35 +171,36 b' Some notes for core developers when merging third-party contributions'
170 171
171 172 Core developers, who ultimately merge any approved branch (from themselves,
172 173 another developer, or any third-party contribution) will typically use
173 :command:`bzr merge` to merge the branch into the trunk and push it to the main
174 Launcphad site. This is a short list of things to keep in mind when doing this
175 process, so that the project history is easy to understand in the long run, and
176 that generating release notes is as painless and accurate as possible.
177
178 - When you merge any non-trivial functionality (from one small bug fix to a big
179 feature branch), please remember to always edit the changes_ file
180 accordingly. This file has one main section for each release, and if you
181 edit it as you go, noting what new features, bug fixes or API changes you
182 have made, the release notes will be almost finished when they are needed
183 later. This is much easier if done when you merge the work, rather than
184 weeks or months later by re-reading a massive Bazaar log.
185
186 - When big merges are done, the practice of putting a summary commit message in
187 the merge is *extremely* useful. It makes this kind of job much nicer,
174 :command:`bzr merge` to merge the branch into the trunk and push it to the
175 main Launcphad site. This is a short list of things to keep in mind when doing
176 this process, so that the project history is easy to understand in the long
177 run, and that generating release notes is as painless and accurate as
178 possible.
179
180 - When you merge any non-trivial functionality (from one small bug fix to a
181 big feature branch), please remember to always edit the :file:`changes.txt`
182 file accordingly. This file has one main section for each release, and if
183 you edit it as you go, noting what new features, bug fixes or API changes
184 you have made, the release notes will be almost finished when they are
185 needed later. This is much easier if done when you merge the work, rather
186 than weeks or months later by re-reading a massive Bazaar log.
187
188 - When big merges are done, the practice of putting a summary commit message
189 in the merge is *extremely* useful. It makes this kind of job much nicer,
188 190 because that summary log message can be almost copy/pasted without changes,
189 191 if it was well written, rather than dissecting the next-level messages from
190 192 the individual commits.
191 193
192 194 - It's important that we remember to always credit who gave us something if
193 it's not the committer. In general, we have been fairly good on this front,
194 this is just a reminder to keep things up. As a note, if you are ever
195 it's not the committer. In general, we have been fairly good on this front,
196 this is just a reminder to keep things up. As a note, if you are ever
195 197 committing something that is completely (or almost so) a third-party
196 198 contribution, do the commit as::
197 199
198 200 $ bzr commit --author="Someone Else"
199 201
200 202 This way it will show that name separately in the log, which makes it even
201 easier to spot. Obviously we often rework third party contributions
203 easier to spot. Obviously we often rework third party contributions
202 204 extensively, but this is still good to keep in mind for cases when we don't
203 205 touch the code too much.
204 206
@@ -76,19 +76,9 b' Procedure'
76 76 1. Move the file to its new location with its new name.
77 77 2. Rename all import statements to reflect the change.
78 78 3. Run PyFlakes on each changes module.
79 3. Add tests/test_imports.py to test it.
79 4. Add tests/test_imports.py to test it.
80 80
81 81 Status
82 82 ======
83 83
84 The new subpackages have been created and the top-level modules have been
85 moved and renamed. Import tests have been created for all of the moved and
86 renamed modules. The build infrastructure (setup.py and friends) have been
87 updated and tested on Mac and Windows. Finally, a compatibility layer has been
88 added for iplib, ipapi and Shell. The follow things still need to be done::
89
90 * I need to modify iptests to properly skip modules that are no longer top
91 level modules.
92
93 * When running python setup.py sdist, the Sphinx API docs fail to build
94 because of something going on with IPython.core.fakemodule
84 This branch was merged into trunk in early August of 2009.
@@ -4,42 +4,34 b''
4 4 Development roadmap
5 5 ===================
6 6
7 IPython is an ambitious project that is still under heavy development. However, we want IPython to become useful to as many people as possible, as quickly as possible. To help us accomplish this, we are laying out a roadmap of where we are headed and what needs to happen to get there. Hopefully, this will help the IPython developers figure out the best things to work on for each upcoming release.
7 IPython is an ambitious project that is still under heavy development.
8 However, we want IPython to become useful to as many people as possible, as
9 quickly as possible. To help us accomplish this, we are laying out a roadmap
10 of where we are headed and what needs to happen to get there. Hopefully, this
11 will help the IPython developers figure out the best things to work on for
12 each upcoming release.
8 13
9 14 Work targeted to particular releases
10 15 ====================================
11 16
12 Release 0.10
13 ------------
14
15 * Initial refactor of :command:`ipcluster`.
16
17 * Better TextMate integration.
18
19 * Merge in the daemon branch.
20
21 17 Release 0.11
22 18 ------------
23 19
24 * Refactor the configuration system and command line options for
25 :command:`ipengine` and :command:`ipcontroller`. This will include the
26 creation of cluster directories that encapsulate all the configuration
27 files, log files and security related files for a particular cluster.
20 * [DONE] Full module and package reorganization.
21
22 * [DONE] Removal of the threaded shells and new implementation of GUI support
23 based on ``PyOSInputHook``.
28 24
29 * Refactor :command:`ipcluster` to support the new configuration system.
25 * Refactor the configuration system.
30 26
31 * Refactor the daemon stuff to support the new configuration system.
27 * Prepare to refactor IPython's core by creating a new component and
28 application system.
32 29
33 * Merge back in the core of the notebook.
34 30
35 31 Release 0.12
36 32 ------------
37 33
38 * Fully integrate process startup with the daemons for full process
39 management.
40 34
41 * Make the capabilites of :command:`ipcluster` available from simple Python
42 classes.
43 35
44 36 Major areas of work
45 37 ===================
@@ -25,71 +25,16 b' $HOME resolves to C:\\\\Documents and Settings\\\\YourUserName in most'
25 25 instances. In the rest of this text, we will refer to this directory as
26 26 IPYTHONDIR.
27 27
28 .. _Threading options:
29 28
30 29
31 30 Special Threading Options
32 31 -------------------------
33 32
34 The following special options are ONLY valid at the beginning of the
35 command line, and not later. This is because they control the initial-
36 ization of ipython itself, before the normal option-handling mechanism
37 is active.
38
39 -gthread, -qthread, -q4thread, -wthread, -pylab:
40 Only one of these can be given, and it can only be given as
41 the first option passed to IPython (it will have no effect in
42 any other position). They provide threading support for the
43 GTK, Qt (versions 3 and 4) and WXPython toolkits, and for the
44 matplotlib library.
45
46 With any of the first four options, IPython starts running a
47 separate thread for the graphical toolkit's operation, so that
48 you can open and control graphical elements from within an
49 IPython command line, without blocking. All four provide
50 essentially the same functionality, respectively for GTK, Qt3,
51 Qt4 and WXWidgets (via their Python interfaces).
52
53 Note that with -wthread, you can additionally use the
54 -wxversion option to request a specific version of wx to be
55 used. This requires that you have the wxversion Python module
56 installed, which is part of recent wxPython distributions.
57
58 If -pylab is given, IPython loads special support for the mat
59 plotlib library (http://matplotlib.sourceforge.net), allowing
60 interactive usage of any of its backends as defined in the
61 user's ~/.matplotlib/matplotlibrc file. It automatically
62 activates GTK, Qt or WX threading for IPyhton if the choice of
63 matplotlib backend requires it. It also modifies the %run
64 command to correctly execute (without blocking) any
65 matplotlib-based script which calls show() at the end.
66
67 -tk
68 The -g/q/q4/wthread options, and -pylab (if matplotlib is
69 configured to use GTK, Qt3, Qt4 or WX), will normally block Tk
70 graphical interfaces. This means that when either GTK, Qt or WX
71 threading is active, any attempt to open a Tk GUI will result in a
72 dead window, and possibly cause the Python interpreter to crash.
73 An extra option, -tk, is available to address this issue. It can
74 only be given as a second option after any of the above (-gthread,
75 -wthread or -pylab).
76
77 If -tk is given, IPython will try to coordinate Tk threading
78 with GTK, Qt or WX. This is however potentially unreliable, and
79 you will have to test on your platform and Python configuration to
80 determine whether it works for you. Debian users have reported
81 success, apparently due to the fact that Debian builds all of Tcl,
82 Tk, Tkinter and Python with pthreads support. Under other Linux
83 environments (such as Fedora Core 2/3), this option has caused
84 random crashes and lockups of the Python interpreter. Under other
85 operating systems (Mac OSX and Windows), you'll need to try it to
86 find out, since currently no user reports are available.
87
88 There is unfortunately no way for IPython to determine at run time
89 whether -tk will work reliably or not, so you will need to do some
90 experiments before relying on it for regular work.
91
92
33 Previously IPython had command line options for controlling GUI event loop
34 integration (-gthread, -qthread, -q4thread, -wthread, -pylab). As of IPython
35 version 0.11, these have been deprecated. Please see the new ``%gui``
36 magic command or :ref:`this section <gui_support>` for details on the new
37 interface.
93 38
94 39 Regular Options
95 40 ---------------
@@ -109,16 +54,8 b' All options with a [no] prepended can be specified in negated form'
109 54 -help print a help message and exit.
110 55
111 56 -pylab
112 this can only be given as the first option passed to IPython
113 (it will have no effect in any other position). It adds
114 special support for the matplotlib library
115 (http://matplotlib.sourceforge.ne), allowing interactive usage
116 of any of its backends as defined in the user's .matplotlibrc
117 file. It automatically activates GTK or WX threading for
118 IPyhton if the choice of matplotlib backend requires it. It
119 also modifies the %run command to correctly execute (without
120 blocking) any matplotlib-based script which calls show() at
121 the end. See `Matplotlib support`_ for more details.
57 Deprecated. See :ref:`Matplotlib support <matplotlib_support>`
58 for more details.
122 59
123 60 -autocall <val>
124 61 Make IPython automatically call any callable object even if you
@@ -367,9 +304,7 b' All options with a [no] prepended can be specified in negated form'
367 304 -Version print version information and exit.
368 305
369 306 -wxversion <string>
370 Select a specific version of wxPython (used in conjunction
371 with -wthread). Requires the wxversion module, part of recent
372 wxPython distributions
307 Deprecated.
373 308
374 309 -xmode <modename>
375 310
@@ -1435,77 +1370,74 b' from math import * # math MUST be imported BEFORE PhysicalQInteractive'
1435 1370 from IPython.extensions.PhysicalQInteractive import *
1436 1371 import IPython.extensions.PhysicalQInput
1437 1372
1373 .. _gui_support:
1438 1374
1439 Threading support
1440 =================
1375 GUI event loop support support
1376 ==============================
1377
1378 .. versionadded:: 0.11
1379 The ``%gui`` magic and :mod:`IPython.lib.inputhook`.
1380
1381 IPython has excellent support for working interactively with Graphical User
1382 Interface (GUI) toolkits, such as wxPython, PyQt4, PyGTK and Tk. This is
1383 implemented using Python's builtin ``PyOSInputHook`` hook. This implementation
1384 is extremely robust compared to our previous threaded based version. The
1385 advantages of
1386
1387 * GUIs can be enabled and disabled dynamically at runtime.
1388 * The active GUI can be switched dynamically at runtime.
1389 * In some cases, multiple GUIs can run simultaneously with no problems.
1390 * There is a developer API in :mod:`IPython.lib.inputhook` for customizing
1391 all of these things.
1392
1393 For users, enabling GUI event loop integration is simple. You simple use the
1394 ``%gui`` magic as follows::
1395
1396 %gui [-a] [GUINAME]
1397
1398 With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME``
1399 arguments are ``wx``, ``qt4``, ``gtk`` and ``tk``. The ``-a`` option will
1400 create and return a running application object for the selected GUI toolkit.
1401
1402 This to use wxPython interactively and create a running :class:`wx.App`
1403 object, do::
1404
1405 %gui -a wx
1406
1407 For information on IPython's Matplotlib integration (and the ``pylab`` mode)
1408 see :ref:`this section <matplotlib_support>`.
1441 1409
1442 WARNING: The threading support is still somewhat experimental, and it
1443 has only seen reasonable testing under Linux. Threaded code is
1444 particularly tricky to debug, and it tends to show extremely
1445 platform-dependent behavior. Since I only have access to Linux machines,
1446 I will have to rely on user's experiences and assistance for this area
1447 of IPython to improve under other platforms.
1448
1449 IPython, via the -gthread , -qthread, -q4thread and -wthread options
1450 (described in Sec. `Threading options`_), can run in
1451 multithreaded mode to support pyGTK, Qt3, Qt4 and WXPython applications
1452 respectively. These GUI toolkits need to control the python main loop of
1453 execution, so under a normal Python interpreter, starting a pyGTK, Qt3,
1454 Qt4 or WXPython application will immediately freeze the shell.
1455
1456 IPython, with one of these options (you can only use one at a time),
1457 separates the graphical loop and IPython's code execution run into
1458 different threads. This allows you to test interactively (with %run, for
1459 example) your GUI code without blocking.
1460
1461 A nice mini-tutorial on using IPython along with the Qt Designer
1462 application is available at the SciPy wiki:
1463 http://www.scipy.org/Cookbook/Matplotlib/Qt_with_IPython_and_Designer.
1464
1465
1466 Tk issues
1467 ---------
1468
1469 As indicated in Sec. `Threading options`_, a special -tk option is
1470 provided to try and allow Tk graphical applications to coexist
1471 interactively with WX, Qt or GTK ones. Whether this works at all,
1472 however, is very platform and configuration dependent. Please
1473 experiment with simple test cases before committing to using this
1474 combination of Tk and GTK/Qt/WX threading in a production environment.
1475
1476
1477 I/O pitfalls
1478 ------------
1479
1480 Be mindful that the Python interpreter switches between threads every
1481 $N$ bytecodes, where the default value as of Python 2.3 is $N=100.$ This
1482 value can be read by using the sys.getcheckinterval() function, and it
1483 can be reset via sys.setcheckinterval(N). This switching of threads can
1484 cause subtly confusing effects if one of your threads is doing file I/O.
1485 In text mode, most systems only flush file buffers when they encounter a
1486 '\n'. An instruction as simple as::
1487
1488 print >> filehandle, ''hello world''
1489
1490 actually consists of several bytecodes, so it is possible that the
1491 newline does not reach your file before the next thread switch.
1492 Similarly, if you are writing to a file in binary mode, the file won't
1493 be flushed until the buffer fills, and your other thread may see
1494 apparently truncated files.
1495
1496 For this reason, if you are using IPython's thread support and have (for
1497 example) a GUI application which will read data generated by files
1498 written to from the IPython thread, the safest approach is to open all
1499 of your files in unbuffered mode (the third argument to the file/open
1500 function is the buffering value)::
1501
1502 filehandle = open(filename,mode,0)
1503
1504 This is obviously a brute force way of avoiding race conditions with the
1505 file buffering. If you want to do it cleanly, and you have a resource
1506 which is being shared by the interactive IPython loop and your GUI
1507 thread, you should really handle it with thread locking and
1508 syncrhonization properties. The Python documentation discusses these.
1410 For developers that want to use IPython's GUI event loop integration in
1411 the form of a library, the capabilities are exposed in library form
1412 in the :mod:`IPython.lib.inputhook`. Interested developers should see the
1413 module docstrings for more information.
1414
1415 .. _matplotlib_support:
1416
1417 Plotting with matplotlib
1418 ========================
1419
1420
1421 `Matplotlib`_ provides high quality 2D and
1422 3D plotting for Python. Matplotlib can produce plots on screen using a variety
1423 of GUI toolkits, including Tk, PyGTK, PyQt4 and wxPython. It also provides a
1424 number of commands useful for scientific computing, all with a syntax
1425 compatible with that of the popular Matlab program.
1426
1427 Many IPython users have come to rely on IPython's ``-pylab`` mode which
1428 automates the integration of Matplotlib with IPython. We are still in the
1429 process of working with the Matplotlib developers to finalize the new pylab
1430 API, but for now you can use Matplotlib interactively using the following
1431 commands::
1432
1433 %gui -a wx
1434 import matplotlib
1435 matplotlib.use('wxagg')
1436 from matplotlib import pylab
1437 pylab.interactive(True)
1438
1439 All of this will soon be automated as Matplotlib beings to include
1440 new logic that uses our new GUI support.
1509 1441
1510 1442 .. _interactive_demos:
1511 1443
@@ -1603,30 +1535,5 b' divisions are allowed. If you want to be able to open an IPython'
1603 1535 instance at an arbitrary point in a program, you can use IPython's
1604 1536 embedding facilities, described in detail in Sec. 9
1605 1537
1538 .. [Matplotlib] Matplotlib. http://matplotlib.sourceforge.net
1606 1539
1607 .. _Matplotlib support:
1608
1609 Plotting with matplotlib
1610 ========================
1611
1612 The matplotlib library (http://matplotlib.sourceforge.net
1613 http://matplotlib.sourceforge.net) provides high quality 2D plotting for
1614 Python. Matplotlib can produce plots on screen using a variety of GUI
1615 toolkits, including Tk, GTK and WXPython. It also provides a number of
1616 commands useful for scientific computing, all with a syntax compatible
1617 with that of the popular Matlab program.
1618
1619 IPython accepts the special option -pylab (see :ref:`here
1620 <command_line_options>`). This configures it to support matplotlib, honoring
1621 the settings in the .matplotlibrc file. IPython will detect the user's choice
1622 of matplotlib GUI backend, and automatically select the proper threading model
1623 to prevent blocking. It also sets matplotlib in interactive mode and modifies
1624 %run slightly, so that any matplotlib-based script can be executed using %run
1625 and the final show() command does not block the interactive shell.
1626
1627 The -pylab option must be given first in order for IPython to configure its
1628 threading mode. However, you can still issue other options afterwards. This
1629 allows you to have a matplotlib-based environment customized with additional
1630 modules using the standard IPython profile mechanism (see :ref:`here
1631 <profiles>`): ``ipython -pylab -p myprofile`` will load the profile defined in
1632 ipythonrc-myprofile after configuring matplotlib.
@@ -13,4 +13,3 b' Using IPython for parallel computing'
13 13 parallel_task.txt
14 14 parallel_mpi.txt
15 15 parallel_security.txt
16 visionhpc.txt
@@ -90,13 +90,15 b' asynchronous interface to a set of engines.'
90 90 Because the controller listens on a network port for engines to
91 91 connect to it, it must be started *before* any engines are started.
92 92
93 The controller also provides a single point of contact for users who wish
94 to utilize the engines connected to the controller. There are different
95 ways of working with a controller. In IPython these ways correspond to different interfaces that the controller is adapted to. Currently we have two default interfaces to the controller:
93 The controller also provides a single point of contact for users who wish to
94 utilize the engines connected to the controller. There are different ways of
95 working with a controller. In IPython these ways correspond to different
96 interfaces that the controller is adapted to. Currently we have two default
97 interfaces to the controller:
96 98
97 99 * The MultiEngine interface, which provides the simplest possible way of
98 100 working with engines interactively.
99 * The Task interface, which provides presents the engines as a load balanced
101 * The Task interface, which presents the engines as a load balanced
100 102 task farming system.
101 103
102 104 Advanced users can easily add new custom interfaces to enable other
@@ -121,11 +123,30 b' interface. Here are the two default clients:'
121 123 Security
122 124 --------
123 125
124 By default (as long as `pyOpenSSL` is installed) all network connections between the controller and engines and the controller and clients are secure. What does this mean? First of all, all of the connections will be encrypted using SSL. Second, the connections are authenticated. We handle authentication in a capability based security model [Capability]_. In this model, a "capability (known in some systems as a key) is a communicable, unforgeable token of authority". Put simply, a capability is like a key to your house. If you have the key to your house, you can get in. If not, you can't.
125
126 In our architecture, the controller is the only process that listens on network ports, and is thus responsible to creating these keys. In IPython, these keys are known as Foolscap URLs, or FURLs, because of the underlying network protocol we are using. As a user, you don't need to know anything about the details of these FURLs, other than that when the controller starts, it saves a set of FURLs to files named :file:`something.furl`. The default location of these files is the :file:`~./ipython/security` directory.
127
128 To connect and authenticate to the controller an engine or client simply needs to present an appropriate FURL (that was originally created by the controller) to the controller. Thus, the FURL files need to be copied to a location where the clients and engines can find them. Typically, this is the :file:`~./ipython/security` directory on the host where the client/engine is running (which could be a different host than the controller). Once the FURL files are copied over, everything should work fine.
126 By default (as long as `pyOpenSSL` is installed) all network connections
127 between the controller and engines and the controller and clients are secure.
128 What does this mean? First of all, all of the connections will be encrypted
129 using SSL. Second, the connections are authenticated. We handle authentication
130 in a capability based security model [Capability]_. In this model, a
131 "capability (known in some systems as a key) is a communicable, unforgeable
132 token of authority". Put simply, a capability is like a key to your house. If
133 you have the key to your house, you can get in. If not, you can't.
134
135 In our architecture, the controller is the only process that listens on
136 network ports, and is thus responsible to creating these keys. In IPython,
137 these keys are known as Foolscap URLs, or FURLs, because of the underlying
138 network protocol we are using. As a user, you don't need to know anything
139 about the details of these FURLs, other than that when the controller starts,
140 it saves a set of FURLs to files named :file:`something.furl`. The default
141 location of these files is the :file:`~./ipython/security` directory.
142
143 To connect and authenticate to the controller an engine or client simply needs
144 to present an appropriate FURL (that was originally created by the controller)
145 to the controller. Thus, the FURL files need to be copied to a location where
146 the clients and engines can find them. Typically, this is the
147 :file:`~./ipython/security` directory on the host where the client/engine is
148 running (which could be a different host than the controller). Once the FURL
149 files are copied over, everything should work fine.
129 150
130 151 Currently, there are three FURL files that the controller creates:
131 152
@@ -149,12 +170,16 b' can be found :ref:`here <parallelsecurity>`.'
149 170 Getting Started
150 171 ===============
151 172
152 To use IPython for parallel computing, you need to start one instance of
153 the controller and one or more instances of the engine. Initially, it is best to simply start a controller and engines on a single host using the :command:`ipcluster` command. To start a controller and 4 engines on you localhost, just do::
173 To use IPython for parallel computing, you need to start one instance of the
174 controller and one or more instances of the engine. Initially, it is best to
175 simply start a controller and engines on a single host using the
176 :command:`ipcluster` command. To start a controller and 4 engines on your
177 localhost, just do::
154 178
155 179 $ ipcluster local -n 4
156 180
157 More details about starting the IPython controller and engines can be found :ref:`here <parallel_process>`
181 More details about starting the IPython controller and engines can be found
182 :ref:`here <parallel_process>`
158 183
159 184 Once you have started the IPython controller and one or more engines, you
160 185 are ready to use the engines to do something useful. To make sure
@@ -184,7 +209,12 b' everything is working correctly, try the following commands:'
184 209 [3] In [1]: print "Hello World"
185 210 [3] Out[1]: Hello World
186 211
187 Remember, a client also needs to present a FURL file to the controller. How does this happen? When a multiengine client is created with no arguments, the client tries to find the corresponding FURL file in the local :file:`~./ipython/security` directory. If it finds it, you are set. If you have put the FURL file in a different location or it has a different name, create the client like this::
212 Remember, a client also needs to present a FURL file to the controller. How
213 does this happen? When a multiengine client is created with no arguments, the
214 client tries to find the corresponding FURL file in the local
215 :file:`~./ipython/security` directory. If it finds it, you are set. If you
216 have put the FURL file in a different location or it has a different name,
217 create the client like this::
188 218
189 219 mec = client.MultiEngineClient('/path/to/my/ipcontroller-mec.furl')
190 220
@@ -192,7 +222,9 b' Same thing hold true of creating a task client::'
192 222
193 223 tc = client.TaskClient('/path/to/my/ipcontroller-tc.furl')
194 224
195 You are now ready to learn more about the :ref:`MultiEngine <parallelmultiengine>` and :ref:`Task <paralleltask>` interfaces to the controller.
225 You are now ready to learn more about the :ref:`MultiEngine
226 <parallelmultiengine>` and :ref:`Task <paralleltask>` interfaces to the
227 controller.
196 228
197 229 .. note::
198 230
@@ -4,9 +4,16 b''
4 4 Using MPI with IPython
5 5 =======================
6 6
7 Often, a parallel algorithm will require moving data between the engines. One way of accomplishing this is by doing a pull and then a push using the multiengine client. However, this will be slow as all the data has to go through the controller to the client and then back through the controller, to its final destination.
7 Often, a parallel algorithm will require moving data between the engines. One
8 way of accomplishing this is by doing a pull and then a push using the
9 multiengine client. However, this will be slow as all the data has to go
10 through the controller to the client and then back through the controller, to
11 its final destination.
8 12
9 A much better way of moving data between engines is to use a message passing library, such as the Message Passing Interface (MPI) [MPI]_. IPython's parallel computing architecture has been designed from the ground up to integrate with MPI. This document describes how to use MPI with IPython.
13 A much better way of moving data between engines is to use a message passing
14 library, such as the Message Passing Interface (MPI) [MPI]_. IPython's
15 parallel computing architecture has been designed from the ground up to
16 integrate with MPI. This document describes how to use MPI with IPython.
10 17
11 18 Additional installation requirements
12 19 ====================================
@@ -35,12 +42,15 b' To use code that calls MPI, there are typically two things that MPI requires.'
35 42 :command:`mpiexec` or a batch system (like PBS) that has MPI support.
36 43 2. Once the process starts, it must call :func:`MPI_Init`.
37 44
38 There are a couple of ways that you can start the IPython engines and get these things to happen.
45 There are a couple of ways that you can start the IPython engines and get
46 these things to happen.
39 47
40 48 Automatic starting using :command:`mpiexec` and :command:`ipcluster`
41 49 --------------------------------------------------------------------
42 50
43 The easiest approach is to use the `mpiexec` mode of :command:`ipcluster`, which will first start a controller and then a set of engines using :command:`mpiexec`::
51 The easiest approach is to use the `mpiexec` mode of :command:`ipcluster`,
52 which will first start a controller and then a set of engines using
53 :command:`mpiexec`::
44 54
45 55 $ ipcluster mpiexec -n 4
46 56
@@ -50,7 +60,8 b' stop and clean up the controller and engines.'
50 60 Manual starting using :command:`mpiexec`
51 61 ----------------------------------------
52 62
53 If you want to start the IPython engines using the :command:`mpiexec`, just do::
63 If you want to start the IPython engines using the :command:`mpiexec`, just
64 do::
54 65
55 66 $ mpiexec -n 4 ipengine --mpi=mpi4py
56 67
@@ -64,14 +75,20 b' starting the engines with::'
64 75 Automatic starting using PBS and :command:`ipcluster`
65 76 -----------------------------------------------------
66 77
67 The :command:`ipcluster` command also has built-in integration with PBS. For more information on this approach, see our documentation on :ref:`ipcluster <parallel_process>`.
78 The :command:`ipcluster` command also has built-in integration with PBS. For
79 more information on this approach, see our documentation on :ref:`ipcluster
80 <parallel_process>`.
68 81
69 82 Actually using MPI
70 83 ==================
71 84
72 Once the engines are running with MPI enabled, you are ready to go. You can now call any code that uses MPI in the IPython engines. And, all of this can be done interactively. Here we show a simple example that uses mpi4py [mpi4py]_.
85 Once the engines are running with MPI enabled, you are ready to go. You can
86 now call any code that uses MPI in the IPython engines. And, all of this can
87 be done interactively. Here we show a simple example that uses mpi4py
88 [mpi4py]_.
73 89
74 First, lets define a simply function that uses MPI to calculate the sum of a distributed array. Save the following text in a file called :file:`psum.py`:
90 First, lets define a simply function that uses MPI to calculate the sum of a
91 distributed array. Save the following text in a file called :file:`psum.py`:
75 92
76 93 .. sourcecode:: python
77 94
@@ -86,7 +103,9 b' Now, start an IPython cluster in the same directory as :file:`psum.py`::'
86 103
87 104 $ ipcluster mpiexec -n 4
88 105
89 Finally, connect to the cluster and use this function interactively. In this case, we create a random array on each engine and sum up all the random arrays using our :func:`psum` function:
106 Finally, connect to the cluster and use this function interactively. In this
107 case, we create a random array on each engine and sum up all the random arrays
108 using our :func:`psum` function:
90 109
91 110 .. sourcecode:: ipython
92 111
@@ -58,7 +58,10 b' Here we see that there are four engines ready to do work for us.'
58 58 Quick and easy parallelism
59 59 ==========================
60 60
61 In many cases, you simply want to apply a Python function to a sequence of objects, but *in parallel*. The multiengine interface provides two simple ways of accomplishing this: a parallel version of :func:`map` and ``@parallel`` function decorator.
61 In many cases, you simply want to apply a Python function to a sequence of
62 objects, but *in parallel*. The multiengine interface provides two simple ways
63 of accomplishing this: a parallel version of :func:`map` and ``@parallel``
64 function decorator.
62 65
63 66 Parallel map
64 67 ------------
@@ -90,7 +93,9 b' parallel version of :meth:`map` that works just like its serial counterpart:'
90 93 Parallel function decorator
91 94 ---------------------------
92 95
93 Parallel functions are just like normal function, but they can be called on sequences and *in parallel*. The multiengine interface provides a decorator that turns any Python function into a parallel function:
96 Parallel functions are just like normal function, but they can be called on
97 sequences and *in parallel*. The multiengine interface provides a decorator
98 that turns any Python function into a parallel function:
94 99
95 100 .. sourcecode:: ipython
96 101
@@ -667,7 +672,9 b' more other types of exceptions. Here is how it works:'
667 672 [2:execute]: ZeroDivisionError: integer division or modulo by zero
668 673 [3:execute]: ZeroDivisionError: integer division or modulo by zero
669 674
670 Notice how the error message printed when :exc:`CompositeError` is raised has information about the individual exceptions that were raised on each engine. If you want, you can even raise one of these original exceptions:
675 Notice how the error message printed when :exc:`CompositeError` is raised has
676 information about the individual exceptions that were raised on each engine.
677 If you want, you can even raise one of these original exceptions:
671 678
672 679 .. sourcecode:: ipython
673 680
@@ -15,14 +15,20 b' Broadly speaking, there are two ways of going about starting a controller and en'
15 15 * In a more manual way using the :command:`ipcontroller` and
16 16 :command:`ipengine` commands.
17 17
18 This document describes both of these methods. We recommend that new users start with the :command:`ipcluster` command as it simplifies many common usage cases.
18 This document describes both of these methods. We recommend that new users
19 start with the :command:`ipcluster` command as it simplifies many common usage
20 cases.
19 21
20 22 General considerations
21 23 ======================
22 24
23 Before delving into the details about how you can start a controller and engines using the various methods, we outline some of the general issues that come up when starting the controller and engines. These things come up no matter which method you use to start your IPython cluster.
25 Before delving into the details about how you can start a controller and
26 engines using the various methods, we outline some of the general issues that
27 come up when starting the controller and engines. These things come up no
28 matter which method you use to start your IPython cluster.
24 29
25 Let's say that you want to start the controller on ``host0`` and engines on hosts ``host1``-``hostn``. The following steps are then required:
30 Let's say that you want to start the controller on ``host0`` and engines on
31 hosts ``host1``-``hostn``. The following steps are then required:
26 32
27 33 1. Start the controller on ``host0`` by running :command:`ipcontroller` on
28 34 ``host0``.
@@ -41,12 +47,15 b' at that location.'
41 47 The final step required required to actually use the running controller from a
42 48 client is to move the FURL files :file:`ipcontroller-mec.furl` and
43 49 :file:`ipcontroller-tc.furl` from ``host0`` to the host where the clients will
44 be run. If these file are put into the :file:`~/.ipython/security` directory of the client's host, they will be found automatically. Otherwise, the full path to them has to be passed to the client's constructor.
50 be run. If these file are put into the :file:`~/.ipython/security` directory
51 of the client's host, they will be found automatically. Otherwise, the full
52 path to them has to be passed to the client's constructor.
45 53
46 54 Using :command:`ipcluster`
47 55 ==========================
48 56
49 The :command:`ipcluster` command provides a simple way of starting a controller and engines in the following situations:
57 The :command:`ipcluster` command provides a simple way of starting a
58 controller and engines in the following situations:
50 59
51 60 1. When the controller and engines are all run on localhost. This is useful
52 61 for testing or running on a multicore computer.
@@ -110,11 +119,20 b' This does the following:'
110 119 1. Starts the IPython controller on current host.
111 120 2. Uses :command:`mpiexec` to start 4 engines.
112 121
113 On newer MPI implementations (such as OpenMPI), this will work even if you don't make any calls to MPI or call :func:`MPI_Init`. However, older MPI implementations actually require each process to call :func:`MPI_Init` upon starting. The easiest way of having this done is to install the mpi4py [mpi4py]_ package and then call ipcluster with the ``--mpi`` option::
122 On newer MPI implementations (such as OpenMPI), this will work even if you
123 don't make any calls to MPI or call :func:`MPI_Init`. However, older MPI
124 implementations actually require each process to call :func:`MPI_Init` upon
125 starting. The easiest way of having this done is to install the mpi4py
126 [mpi4py]_ package and then call ipcluster with the ``--mpi`` option::
114 127
115 128 $ ipcluster mpiexec -n 4 --mpi=mpi4py
116 129
117 Unfortunately, even this won't work for some MPI implementations. If you are having problems with this, you will likely have to use a custom Python executable that itself calls :func:`MPI_Init` at the appropriate time. Fortunately, mpi4py comes with such a custom Python executable that is easy to install and use. However, this custom Python executable approach will not work with :command:`ipcluster` currently.
130 Unfortunately, even this won't work for some MPI implementations. If you are
131 having problems with this, you will likely have to use a custom Python
132 executable that itself calls :func:`MPI_Init` at the appropriate time.
133 Fortunately, mpi4py comes with such a custom Python executable that is easy to
134 install and use. However, this custom Python executable approach will not work
135 with :command:`ipcluster` currently.
118 136
119 137 Additional command line options for this mode can be found by doing::
120 138
@@ -126,7 +144,9 b' More details on using MPI with IPython can be found :ref:`here <parallelmpi>`.'
126 144 Using :command:`ipcluster` in PBS mode
127 145 --------------------------------------
128 146
129 The PBS mode uses the Portable Batch System [PBS]_ to start the engines. To use this mode, you first need to create a PBS script template that will be used to start the engines. Here is a sample PBS script template:
147 The PBS mode uses the Portable Batch System [PBS]_ to start the engines. To
148 use this mode, you first need to create a PBS script template that will be
149 used to start the engines. Here is a sample PBS script template:
130 150
131 151 .. sourcecode:: bash
132 152
@@ -161,7 +181,8 b' There are a few important points about this template:'
161 181 5. Depending on the configuration of you system, you may have to set
162 182 environment variables in the script template.
163 183
164 Once you have created such a script, save it with a name like :file:`pbs.template`. Now you are ready to start your job::
184 Once you have created such a script, save it with a name like
185 :file:`pbs.template`. Now you are ready to start your job::
165 186
166 187 $ ipcluster pbs -n 128 --pbs-script=pbs.template
167 188
@@ -175,9 +196,11 b' Using :command:`ipcluster` in SSH mode'
175 196 The SSH mode uses :command:`ssh` to execute :command:`ipengine` on remote
176 197 nodes and the :command:`ipcontroller` on localhost.
177 198
178 When using using this mode it highly recommended that you have set up SSH keys and are using ssh-agent [SSH]_ for password-less logins.
199 When using using this mode it highly recommended that you have set up SSH keys
200 and are using ssh-agent [SSH]_ for password-less logins.
179 201
180 To use this mode you need a python file describing the cluster, here is an example of such a "clusterfile":
202 To use this mode you need a python file describing the cluster, here is an
203 example of such a "clusterfile":
181 204
182 205 .. sourcecode:: python
183 206
@@ -187,7 +210,8 b' To use this mode you need a python file describing the cluster, here is an examp'
187 210 'host3.example.com' : 1,
188 211 'host4.example.com' : 8 }
189 212
190 Since this is a regular python file usual python syntax applies. Things to note:
213 Since this is a regular python file usual python syntax applies. Things to
214 note:
191 215
192 216 * The `engines` dict, where the keys is the host we want to run engines on and
193 217 the value is the number of engines to run on that host.
@@ -204,12 +228,16 b' start your cluster like so:'
204 228 $ ipcluster ssh --clusterfile /path/to/my/clusterfile.py
205 229
206 230
207 Two helper shell scripts are used to start and stop :command:`ipengine` on remote hosts:
231 Two helper shell scripts are used to start and stop :command:`ipengine` on
232 remote hosts:
208 233
209 234 * sshx.sh
210 235 * engine_killer.sh
211 236
212 Defaults for both of these are contained in the source code for :command:`ipcluster`. The default scripts are written to a local file in a tmep directory and then copied to a temp directory on the remote host and executed from there. On most Unix, Linux and OS X systems this is /tmp.
237 Defaults for both of these are contained in the source code for
238 :command:`ipcluster`. The default scripts are written to a local file in a
239 tmep directory and then copied to a temp directory on the remote host and
240 executed from there. On most Unix, Linux and OS X systems this is /tmp.
213 241
214 242 The default sshx.sh is the following:
215 243
@@ -241,7 +269,9 b' Current limitations of the SSH mode of :command:`ipcluster` are:'
241 269 Using the :command:`ipcontroller` and :command:`ipengine` commands
242 270 ==================================================================
243 271
244 It is also possible to use the :command:`ipcontroller` and :command:`ipengine` commands to start your controller and engines. This approach gives you full control over all aspects of the startup process.
272 It is also possible to use the :command:`ipcontroller` and :command:`ipengine`
273 commands to start your controller and engines. This approach gives you full
274 control over all aspects of the startup process.
245 275
246 276 Starting the controller and engine on your local machine
247 277 --------------------------------------------------------
@@ -253,11 +283,14 b' First start the controller::'
253 283
254 284 $ ipcontroller
255 285
256 Next, start however many instances of the engine you want using (repeatedly) the command::
286 Next, start however many instances of the engine you want using (repeatedly)
287 the command::
257 288
258 289 $ ipengine
259 290
260 The engines should start and automatically connect to the controller using the FURL files in :file:`~./ipython/security`. You are now ready to use the controller and engines from IPython.
291 The engines should start and automatically connect to the controller using the
292 FURL files in :file:`~./ipython/security`. You are now ready to use the
293 controller and engines from IPython.
261 294
262 295 .. warning::
263 296
@@ -279,10 +312,13 b' When the controller and engines are running on different hosts, things are'
279 312 slightly more complicated, but the underlying ideas are the same:
280 313
281 314 1. Start the controller on a host using :command:`ipcontroller`.
282 2. Copy :file:`ipcontroller-engine.furl` from :file:`~./ipython/security` on the controller's host to the host where the engines will run.
315 2. Copy :file:`ipcontroller-engine.furl` from :file:`~./ipython/security` on
316 the controller's host to the host where the engines will run.
283 317 3. Use :command:`ipengine` on the engine's hosts to start the engines.
284 318
285 The only thing you have to be careful of is to tell :command:`ipengine` where the :file:`ipcontroller-engine.furl` file is located. There are two ways you can do this:
319 The only thing you have to be careful of is to tell :command:`ipengine` where
320 the :file:`ipcontroller-engine.furl` file is located. There are two ways you
321 can do this:
286 322
287 323 * Put :file:`ipcontroller-engine.furl` in the :file:`~./ipython/security`
288 324 directory on the engine's host, where it will be found automatically.
@@ -52,7 +52,8 b' When running the IPython kernel to perform a parallel computation, a user'
52 52 utilizes the IPython client to send Python commands and data through the
53 53 IPython controller to the IPython engines, where those commands are executed
54 54 and the data processed. The design of IPython ensures that the client is the
55 only access point for the capabilities of the engines. That is, the only way of addressing the engines is through a client.
55 only access point for the capabilities of the engines. That is, the only way
56 of addressing the engines is through a client.
56 57
57 58 A user can utilize the client to instruct the IPython engines to execute
58 59 arbitrary Python commands. These Python commands can include calls to the
@@ -116,8 +117,8 b' controller creates a number of FURLs for different purposes:'
116 117 to execute.
117 118
118 119 Upon starting, the controller creates these different FURLS and writes them
119 files in the user-read-only directory :file:`$HOME/.ipython/security`. Thus, only the
120 user who starts the controller has access to the FURLs.
120 files in the user-read-only directory :file:`$HOME/.ipython/security`. Thus,
121 only the user who starts the controller has access to the FURLs.
121 122
122 123 For an IPython client or engine to authenticate with a controller, it must
123 124 present the appropriate FURL to the controller upon connecting. If the
@@ -4,9 +4,17 b''
4 4 The IPython task interface
5 5 ==========================
6 6
7 The task interface to the controller presents the engines as a fault tolerant, dynamic load-balanced system or workers. Unlike the multiengine interface, in the task interface, the user have no direct access to individual engines. In some ways, this interface is simpler, but in other ways it is more powerful.
8
9 Best of all the user can use both of these interfaces running at the same time to take advantage or both of their strengths. When the user can break up the user's work into segments that do not depend on previous execution, the task interface is ideal. But it also has more power and flexibility, allowing the user to guide the distribution of jobs, without having to assign tasks to engines explicitly.
7 The task interface to the controller presents the engines as a fault tolerant,
8 dynamic load-balanced system or workers. Unlike the multiengine interface, in
9 the task interface, the user have no direct access to individual engines. In
10 some ways, this interface is simpler, but in other ways it is more powerful.
11
12 Best of all the user can use both of these interfaces running at the same time
13 to take advantage or both of their strengths. When the user can break up the
14 user's work into segments that do not depend on previous execution, the task
15 interface is ideal. But it also has more power and flexibility, allowing the
16 user to guide the distribution of jobs, without having to assign tasks to
17 engines explicitly.
10 18
11 19 Starting the IPython controller and engines
12 20 ===========================================
@@ -44,12 +52,19 b' constructor:'
44 52 Quick and easy parallelism
45 53 ==========================
46 54
47 In many cases, you simply want to apply a Python function to a sequence of objects, but *in parallel*. Like the multiengine interface, the task interface provides two simple ways of accomplishing this: a parallel version of :func:`map` and ``@parallel`` function decorator. However, the verions in the task interface have one important difference: they are dynamically load balanced. Thus, if the execution time per item varies significantly, you should use the versions in the task interface.
55 In many cases, you simply want to apply a Python function to a sequence of
56 objects, but *in parallel*. Like the multiengine interface, the task interface
57 provides two simple ways of accomplishing this: a parallel version of
58 :func:`map` and ``@parallel`` function decorator. However, the verions in the
59 task interface have one important difference: they are dynamically load
60 balanced. Thus, if the execution time per item varies significantly, you
61 should use the versions in the task interface.
48 62
49 63 Parallel map
50 64 ------------
51 65
52 The parallel :meth:`map` in the task interface is similar to that in the multiengine interface:
66 The parallel :meth:`map` in the task interface is similar to that in the
67 multiengine interface:
53 68
54 69 .. sourcecode:: ipython
55 70
@@ -63,7 +78,9 b' The parallel :meth:`map` in the task interface is similar to that in the multien'
63 78 Parallel function decorator
64 79 ---------------------------
65 80
66 Parallel functions are just like normal function, but they can be called on sequences and *in parallel*. The multiengine interface provides a decorator that turns any Python function into a parallel function:
81 Parallel functions are just like normal function, but they can be called on
82 sequences and *in parallel*. The multiengine interface provides a decorator
83 that turns any Python function into a parallel function:
67 84
68 85 .. sourcecode:: ipython
69 86
@@ -79,7 +96,9 b' Parallel functions are just like normal function, but they can be called on sequ'
79 96 More details
80 97 ============
81 98
82 The :class:`TaskClient` has many more powerful features that allow quite a bit of flexibility in how tasks are defined and run. The next places to look are in the following classes:
99 The :class:`TaskClient` has many more powerful features that allow quite a bit
100 of flexibility in how tasks are defined and run. The next places to look are
101 in the following classes:
83 102
84 103 * :class:`IPython.kernel.client.TaskClient`
85 104 * :class:`IPython.kernel.client.StringTask`
@@ -95,5 +114,7 b' The following is an overview of how to use these classes together:'
95 114 4. Use :meth:`TaskClient.get_task_result` to get the results of the
96 115 tasks.
97 116
98 We are in the process of developing more detailed information about the task interface. For now, the docstrings of the :class:`TaskClient`, :class:`StringTask` and :class:`MapTask` classes should be consulted.
117 We are in the process of developing more detailed information about the task
118 interface. For now, the docstrings of the :class:`TaskClient`,
119 :class:`StringTask` and :class:`MapTask` classes should be consulted.
99 120
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now