summaryrefslogtreecommitdiff
path: root/Doc/library/concurrent.futures.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library/concurrent.futures.rst')
-rw-r--r--Doc/library/concurrent.futures.rst45
1 files changed, 35 insertions, 10 deletions
diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst
index eee2285c53..575b1ea56c 100644
--- a/Doc/library/concurrent.futures.rst
+++ b/Doc/library/concurrent.futures.rst
@@ -40,7 +40,7 @@ Executor Objects
.. method:: map(func, *iterables, timeout=None)
- Equivalent to ``map(func, *iterables)`` except *func* is executed
+ Equivalent to :func:`map(func, *iterables) <map>` except *func* is executed
asynchronously and several calls to *func* may be made concurrently. The
returned iterator raises a :exc:`TimeoutError` if
:meth:`~iterator.__next__` is called and the result isn't available
@@ -136,20 +136,23 @@ ThreadPoolExecutor Example
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
+ # Retrieve a single page and report the url and contents
def load_url(url, timeout):
- return urllib.request.urlopen(url, timeout=timeout).read()
+ conn = urllib.request.urlopen(url, timeout=timeout)
+ return conn.readall()
+ # We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
- future_to_url = dict((executor.submit(load_url, url, 60), url)
- for url in URLS)
-
+ # Start the load operations and mark each future with its URL
+ future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
- if future.exception() is not None:
- print('%r generated an exception: %s' % (url,
- future.exception()))
+ try:
+ data = future.result()
+ except Exception as exc:
+ print('%r generated an exception: %s' % (url, exc))
else:
- print('%r page is %d bytes' % (url, len(future.result())))
+ print('%r page is %d bytes' % (url, len(data)))
ProcessPoolExecutor
@@ -170,6 +173,12 @@ to a :class:`ProcessPoolExecutor` will result in deadlock.
of at most *max_workers* processes. If *max_workers* is ``None`` or not
given, it will default to the number of processors on the machine.
+ .. versionchanged:: 3.3
+ When one of the worker processes terminates abruptly, a
+ :exc:`BrokenProcessPool` error is now raised. Previously, behaviour
+ was undefined but operations on the executor or its futures would often
+ freeze or deadlock.
+
.. _processpoolexecutor-example:
@@ -337,6 +346,8 @@ Module Functions
*return_when* indicates when this function should return. It must be one of
the following constants:
+ .. tabularcolumns:: |l|L|
+
+-----------------------------+----------------------------------------+
| Constant | Description |
+=============================+========================================+
@@ -357,7 +368,8 @@ Module Functions
Returns an iterator over the :class:`Future` instances (possibly created by
different :class:`Executor` instances) given by *fs* that yields futures as
- they complete (finished or were cancelled). Any futures that completed
+ they complete (finished or were cancelled). Any futures given by *fs* that
+ are duplicated will be returned once. Any futures that completed
before :func:`as_completed` is called will be yielded first. The returned
iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
called and the result isn't available after *timeout* seconds from the
@@ -371,3 +383,16 @@ Module Functions
:pep:`3148` -- futures - execute computations asynchronously
The proposal which described this feature for inclusion in the Python
standard library.
+
+
+Exception classes
+-----------------
+
+.. exception:: BrokenProcessPool
+
+ Derived from :exc:`RuntimeError`, this exception class is raised when
+ one of the workers of a :class:`ProcessPoolExecutor` has terminated
+ in a non-clean fashion (for example, if it was killed from the outside).
+
+ .. versionadded:: 3.3
+