Skip to content

Commit 30504aa

Browse files
authored
Merge pull request #504 from minrk/return_exceptions
Add AsyncResult.get(return_exceptions=True), map(return_exceptions=True)
2 parents 4ed1b41 + 05ae184 commit 30504aa

File tree

10 files changed

+327
-141
lines changed

10 files changed

+327
-141
lines changed

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117

118118
# The reST default role (used for this markup: `text`) to use for all
119119
# documents.
120-
# default_role = None
120+
default_role = 'literal'
121121

122122
# If true, '()' will be appended to :func: etc. cross-reference text.
123123
# add_function_parentheses = True

docs/source/reference/details.rst

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The following will fail:
3232
.. sourcecode:: ipython
3333

3434
In [3]: A = numpy.zeros(2)
35-
35+
3636
In [4]: def setter(a):
3737
...: a[0]=1
3838
...: return a
@@ -49,7 +49,7 @@ The :attr:`ndarray.flags.writeable` flag will tell you if you can write to an ar
4949
.. sourcecode:: ipython
5050

5151
In [3]: A = numpy.zeros(2)
52-
52+
5353
In [4]: def setter(a):
5454
...: """only copy read-only arrays"""
5555
...: if not a.flags.writeable:
@@ -59,7 +59,7 @@ The :attr:`ndarray.flags.writeable` flag will tell you if you can write to an ar
5959

6060
In [5]: rc[0].apply_sync(setter, A)
6161
Out[5]: array([ 1., 0.])
62-
62+
6363
# note that results will also be read-only:
6464
In [6]: _.flags.writeable
6565
Out[6]: False
@@ -73,14 +73,14 @@ checking and waiting for 0MQ to finish with a buffer.
7373
.. sourcecode:: ipython
7474

7575
In [5]: A = numpy.random.random((1024,1024))
76-
76+
7777
In [6]: view.track=True
78-
78+
7979
In [7]: ar = view.apply_async(lambda x: 2*x, A)
80-
80+
8181
In [8]: ar.sent
8282
Out[8]: False
83-
83+
8484
In [9]: ar.wait_on_send() # blocks until sent is True
8585

8686

@@ -114,7 +114,7 @@ An example of a function that uses a closure:
114114
# inner will have a closure
115115
return a
116116
return inner
117-
117+
118118
f1 = f(1)
119119
f2 = f(2)
120120
f1() # returns 1
@@ -150,7 +150,7 @@ of the global namespace:
150150
.. sourcecode:: ipython
151151

152152
In [10]: view.apply(lambda : a)
153-
153+
154154
# is equivalent to
155155
In [11]: view.pull('a')
156156

@@ -240,10 +240,11 @@ timeout : float/int or None
240240
execute and run
241241
---------------
242242

243-
For executing strings of Python code, :class:`DirectView`s also provide an :meth:`execute` and
244-
a :meth:`run` method, which rather than take functions and arguments, take Python strings.
243+
244+
For executing strings of Python code, :class:`~.DirectView` s also provide an :meth:`~.DirectView.execute` and
245+
a :meth:`~.DirectView.run` method, which rather than take functions and arguments, take Python strings.
245246
`execute` takes a string of Python code to execute, and sends it to the Engine(s). `run`
246-
is the same as `execute`, but for a *file* rather than a string. It is a wrapper that
247+
is the same as `execute`, but for a *filename* rather than a string. It is a wrapper that
247248
does something very similar to ``execute(open(f).read())``.
248249

249250
.. note::
@@ -292,7 +293,7 @@ the index directly to the client's :attr:`ids` list, so:
292293
# negative index
293294
In [2]: rc[-1]
294295
Out[2]: <DirectView 3>
295-
296+
296297
# or slicing:
297298
In [3]: rc[::2]
298299
Out[3]: <DirectView [0,2]>
@@ -303,11 +304,11 @@ are always the same as:
303304

304305
In [2]: rc[rc.ids[-1]]
305306
Out[2]: <DirectView 3>
306-
307+
307308
In [3]: rc[rc.ids[::2]]
308309
Out[3]: <DirectView [0,2]>
309310

310-
Also note that the slice is evaluated at the time of construction of the DirectView, so the
311+
Also note that the slice is evaluated at the time of construction of the DirectView, so the
311312
targets will not change over time if engines are added/removed from the cluster.
312313

313314
Execution via DirectView
@@ -320,7 +321,7 @@ For instance, to get the process ID of all your engines:
320321
.. sourcecode:: ipython
321322

322323
In [5]: import os
323-
324+
324325
In [6]: dview.apply_sync(os.getpid)
325326
Out[6]: [1354, 1356, 1358, 1360]
326327

@@ -329,7 +330,7 @@ Or to see the hostname of the machine they are on:
329330
.. sourcecode:: ipython
330331

331332
In [5]: import socket
332-
333+
333334
In [6]: dview.apply_sync(socket.gethostname)
334335
Out[6]: ['tesla', 'tesla', 'edison', 'edison', 'edison']
335336

@@ -407,23 +408,25 @@ AsyncResults
407408
------------
408409

409410
Our primary representation of the results of remote execution is the :class:`~.AsyncResult`
410-
object, based on the object of the same name in the built-in :mod:`multiprocessing.pool`
411-
module. Our version provides a superset of that interface.
411+
object, based on the object of the same name in the built-in :py:mod:`multiprocessing.pool`
412+
module.
413+
Our version provides a superset of that interface,
414+
and starting in 6.0 is a subclass of :class:`concurrent.futures.Future`.
412415

413-
The basic principle of the AsyncResult is the encapsulation of one or more results not yet completed. Execution methods (including data movement, such as push/pull) will all return
414-
AsyncResults when `block=False`.
416+
The basic principle of the AsyncResult is the encapsulation of one or more results not yet completed.
417+
Execution methods (including data movement, such as push/pull) will all return AsyncResults when `block=False`.
415418

416419
The mp.pool.AsyncResult interface
417420
---------------------------------
418421

419-
The basic interface of the AsyncResult is exactly that of the AsyncResult in :mod:`multiprocessing.pool`, and consists of four methods:
422+
The basic interface of the AsyncResult is exactly that of the AsyncResult in :py:mod:`multiprocessing.pool`, and consists of four methods:
420423

421424
.. AsyncResult spec directly from docs.python.org
422425
423426
.. class:: AsyncResult
424427

425428
The stdlib AsyncResult spec
426-
429+
427430
.. method:: wait([timeout])
428431

429432
Wait until the result is available or until *timeout* seconds pass. This
@@ -592,7 +595,7 @@ clear
592595

593596
shutdown
594597

595-
You can also instruct engines (and the Controller) to terminate from a Client. This
598+
You can also instruct engines (and the Controller) to terminate from a Client. This
596599
can be useful when a job is finished, since you can shutdown all the processes with a
597600
single command.
598601

@@ -632,15 +635,25 @@ and many parallel execution tools in Python, such as the built-in
632635
:py:class:`multiprocessing.Pool` object provide implementations of `map`. All View objects
633636
provide a :meth:`map` method as well, but the load-balanced and direct implementations differ.
634637

635-
Views' map methods can be called on any number of sequences, but they can also take the `block`
636-
and `bound` keyword arguments, just like :meth:`~client.apply`, but *only as keywords*.
638+
Views' map methods can be called on any number of sequences,
639+
but they can also take keyword arguments to influence how the work is distributed.
640+
What keyword arguments are available depends on the view being used.
637641

638-
.. sourcecode:: python
639642

640-
dview.map(*sequences, block=None)
643+
644+
.. class:: ipyparallel.DirectView
645+
:noindex:
646+
647+
.. automethod:: map
648+
649+
.. class:: ipyparallel.LoadBalancedView
650+
:noindex:
651+
652+
.. automethod:: map
653+
654+
.. automethod:: imap
641655

642656

643-
* iter, map_async, reduce
644657

645658
Decorators and RemoteFunctions
646659
==============================

docs/source/tutorial/asyncresult.rst

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,36 @@
44
The AsyncResult object
55
======================
66

7-
In non-blocking mode, :meth:`apply` submits the command to be executed and
8-
then returns a :class:`~.AsyncResult` object immediately. The
9-
AsyncResult object gives you a way of getting a result at a later
7+
In non-blocking mode, :meth:`~.View.apply`, :meth:`~.View.map`, and friends
8+
submit the command to be executed and then return an :class:`~.AsyncResult` object immediately.
9+
The AsyncResult object gives you a way of getting a result at a later
1010
time through its :meth:`get` method, but it also collects metadata
1111
on execution.
1212

1313

14-
Beyond multiprocessing's AsyncResult
14+
Beyond stdlib AsyncResult and Future
1515
====================================
1616

17-
.. Note::
17+
The :class:`AsyncResult` is a subclass of :py:class:`concurrent.futures.Future`.
18+
This means it can be integrated into existing async workflows,
19+
with e.g. :py:func:`asyncio.wrap_future`.
20+
It also extends the :py:class:`~.multiprocessing.AsyncResult` API.
1821

19-
The :class:`~.AsyncResult` object provides a superset of the interface in
20-
:py:class:`multiprocessing.pool.AsyncResult`. See the
21-
`official Python documentation <https://docs.python.org/library/multiprocessing#multiprocessing.pool.AsyncResult>`_
22-
for more on the basics of this interface.
2322

24-
Our AsyncResult objects add a number of convenient features for working with
25-
parallel results, beyond what is provided by the original AsyncResult.
23+
.. seealso::
24+
25+
- :py:class:`multiprocessing.AsyncResult` API
26+
- :py:class:`concurrent.futures.Future` API
27+
28+
In addition to these common features,
29+
our AsyncResult objects add a number of convenient methods for working with parallel results,
30+
beyond what is provided by the standard library classes on which they are based.
2631

2732

2833
get_dict
2934
--------
3035

31-
First, is :meth:`.AsyncResult.get_dict`, which pulls results as a dictionary
36+
:meth:`.AsyncResult.get_dict` pulls results as a dictionary,
3237
keyed by engine_id, rather than a flat list. This is useful for quickly
3338
coordinating or distributing information about all of the engines.
3439

@@ -48,7 +53,7 @@ as in IPython's :file:`examples/parallel/interengine` examples.
4853
Metadata
4954
========
5055

51-
ipyparallel tracks some metadata about the tasks, which is stored
56+
IPython Parallel tracks some metadata about the tasks, which is stored
5257
in the :attr:`.Client.metadata` dict. The AsyncResult object gives you an
5358
interface for this information as well, including timestamps stdout/err,
5459
and engine IDs.
@@ -111,9 +116,9 @@ That is to say, if you treat an AsyncMapResult as if it were a list of your actu
111116
results, it should behave as you would expect, with the only difference being
112117
that you can start iterating through the results before they have even been computed.
113118

114-
This lets you do a dumb version of map/reduce with the builtin Python functions,
119+
This lets you do a simple version of map/reduce with the builtin Python functions,
115120
and the only difference between doing this locally and doing it remotely in parallel
116-
is using the asynchronous view.map instead of the builtin map.
121+
is using the asynchronous ``view.map`` instead of the builtin ``map``.
117122

118123

119124
Here is a simple one-line RMS (root-mean-square) implemented with Python's builtin map/reduce.

0 commit comments

Comments
 (0)