:mod:`concurrent.futures` --- Launching parallel tasks
======================================================

.. module:: concurrent.futures
   :synopsis: Execute computations concurrently using threads or processes.

.. versionadded:: 3.2

**Source code:** :source:`Lib/concurrent/futures/thread.py`
and :source:`Lib/concurrent/futures/process.py`

--------------

The :mod:`concurrent.futures` module provides a high-level interface for
asynchronously executing callables.

The asynchronous execution can be performed with threads, using
:class:`ThreadPoolExecutor`, or separate processes, using
:class:`ProcessPoolExecutor`.  Both implement the same interface, which is
defined by the abstract :class:`Executor` class.


Executor Objects
----------------

.. class:: Executor

   An abstract class that provides methods to execute calls asynchronously.  It
   should not be used directly, but through its concrete subclasses.

    .. method:: submit(fn, *args, **kwargs)

       Schedules the callable, *fn*, to be executed as ``fn(*args **kwargs)``
       and returns a :class:`Future` object representing the execution of the
       callable. ::

          with ThreadPoolExecutor(max_workers=1) as executor:
              future = executor.submit(pow, 323, 1235)
              print(future.result())

    .. method:: map(func, *iterables, timeout=None)

       Equivalent to ``map(func, *iterables)`` except *func* is executed
       asynchronously and several calls to *func* may be made concurrently.  The
       returned iterator raises a :exc:`TimeoutError` if :meth:`__next__()` is
       called and the result isn't available after *timeout* seconds from the
       original call to :meth:`Executor.map`. *timeout* can be an int or a
       float.  If *timeout* is not specified or ``None``, there is no limit to
       the wait time.  If a call raises an exception, then that exception will
       be raised when its value is retrieved from the iterator.

    .. method:: shutdown(wait=True)

       Signal the executor that it should free any resources that it is using
       when the currently pending futures are done executing.  Calls to
       :meth:`Executor.submit` and :meth:`Executor.map` made after shutdown will
       raise :exc:`RuntimeError`.

       If *wait* is ``True`` then this method will not return until all the
       pending futures are done executing and the resources associated with the
       executor have been freed.  If *wait* is ``False`` then this method will
       return immediately and the resources associated with the executor will be
       freed when all pending futures are done executing.  Regardless of the
       value of *wait*, the entire Python program will not exit until all
       pending futures are done executing.

       You can avoid having to call this method explicitly if you use the
       :keyword:`with` statement, which will shutdown the :class:`Executor`
       (waiting as if :meth:`Executor.shutdown` were called with *wait* set to
       ``True``)::

          import shutil
          with ThreadPoolExecutor(max_workers=4) as e:
              e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
              e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
              e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
              e.submit(shutil.copy, 'src3.txt', 'dest4.txt')


ThreadPoolExecutor
------------------

:class:`ThreadPoolExecutor` is a :class:`Executor` subclass that uses a pool of
threads to execute calls asynchronously.

Deadlocks can occur when the callable associated with a :class:`Future` waits on
the results of another :class:`Future`.  For example::

   import time
   def wait_on_b():
       time.sleep(5)
       print(b.result()) # b will never complete because it is waiting on a.
       return 5

   def wait_on_a():
       time.sleep(5)
       print(a.result()) # a will never complete because it is waiting on b.
       return 6


   executor = ThreadPoolExecutor(max_workers=2)
   a = executor.submit(wait_on_b)
   b = executor.submit(wait_on_a)

And::

   def wait_on_future():
       f = executor.submit(pow, 5, 2)
       # This will never complete because there is only one worker thread and
       # it is executing this function.
       print(f.result())

   executor = ThreadPoolExecutor(max_workers=1)
   executor.submit(wait_on_future)


.. class:: ThreadPoolExecutor(max_workers)

   An :class:`Executor` subclass that uses a pool of at most *max_workers*
   threads to execute calls asynchronously.


.. _threadpoolexecutor-example:

ThreadPoolExecutor Example
~~~~~~~~~~~~~~~~~~~~~~~~~~
::

   import concurrent.futures
   import urllib.request

   URLS = ['http://www.foxnews.com/',
           'http://www.cnn.com/',
           'http://europe.wsj.com/',
           'http://www.bbc.co.uk/',
           'http://some-made-up-domain.com/']

   def load_url(url, timeout):
       return urllib.request.urlopen(url, timeout=timeout).read()

   with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
       future_to_url = dict((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()))
           else:
               print('%r page is %d bytes' % (url, len(future.result())))


ProcessPoolExecutor
-------------------

The :class:`ProcessPoolExecutor` class is an :class:`Executor` subclass that
uses a pool of processes to execute calls asynchronously.
:class:`ProcessPoolExecutor` uses the :mod:`multiprocessing` module, which
allows it to side-step the :term:`Global Interpreter Lock` but also means that
only picklable objects can be executed and returned.

Calling :class:`Executor` or :class:`Future` methods from a callable submitted
to a :class:`ProcessPoolExecutor` will result in deadlock.

.. class:: ProcessPoolExecutor(max_workers=None)

   An :class:`Executor` subclass that executes calls asynchronously using a pool
   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:

ProcessPoolExecutor Example
~~~~~~~~~~~~~~~~~~~~~~~~~~~
::

   import concurrent.futures
   import math

   PRIMES = [
       112272535095293,
       112582705942171,
       112272535095293,
       115280095190773,
       115797848077099,
       1099726899285419]

   def is_prime(n):
       if n % 2 == 0:
           return False

       sqrt_n = int(math.floor(math.sqrt(n)))
       for i in range(3, sqrt_n + 1, 2):
           if n % i == 0:
               return False
       return True

   def main():
       with concurrent.futures.ProcessPoolExecutor() as executor:
           for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
               print('%d is prime: %s' % (number, prime))

   if __name__ == '__main__':
       main()


Future Objects
--------------

The :class:`Future` class encapsulates the asynchronous execution of a callable.
:class:`Future` instances are created by :meth:`Executor.submit`.

.. class:: Future

   Encapsulates the asynchronous execution of a callable.  :class:`Future`
   instances are created by :meth:`Executor.submit` and should not be created
   directly except for testing.

    .. method:: cancel()

       Attempt to cancel the call.  If the call is currently being executed and
       cannot be cancelled then the method will return ``False``, otherwise the
       call will be cancelled and the method will return ``True``.

    .. method:: cancelled()

       Return ``True`` if the call was successfully cancelled.

    .. method:: running()

       Return ``True`` if the call is currently being executed and cannot be
       cancelled.

    .. method:: done()

       Return ``True`` if the call was successfully cancelled or finished
       running.

    .. method:: result(timeout=None)

       Return the value returned by the call. If the call hasn't yet completed
       then this method will wait up to *timeout* seconds.  If the call hasn't
       completed in *timeout* seconds, then a :exc:`TimeoutError` will be
       raised. *timeout* can be an int or float.  If *timeout* is not specified
       or ``None``, there is no limit to the wait time.

       If the future is cancelled before completing then :exc:`CancelledError`
       will be raised.

       If the call raised, this method will raise the same exception.

    .. method:: exception(timeout=None)

       Return the exception raised by the call.  If the call hasn't yet
       completed then this method will wait up to *timeout* seconds.  If the
       call hasn't completed in *timeout* seconds, then a :exc:`TimeoutError`
       will be raised.  *timeout* can be an int or float.  If *timeout* is not
       specified or ``None``, there is no limit to the wait time.

       If the future is cancelled before completing then :exc:`CancelledError`
       will be raised.

       If the call completed without raising, ``None`` is returned.

    .. method:: add_done_callback(fn)

       Attaches the callable *fn* to the future.  *fn* will be called, with the
       future as its only argument, when the future is cancelled or finishes
       running.

       Added callables are called in the order that they were added and are
       always called in a thread belonging to the process that added them.  If
       the callable raises a :exc:`Exception` subclass, it will be logged and
       ignored.  If the callable raises a :exc:`BaseException` subclass, the
       behavior is undefined.

       If the future has already completed or been cancelled, *fn* will be
       called immediately.

   The following :class:`Future` methods are meant for use in unit tests and
   :class:`Executor` implementations.

    .. method:: set_running_or_notify_cancel()

       This method should only be called by :class:`Executor` implementations
       before executing the work associated with the :class:`Future` and by unit
       tests.

       If the method returns ``False`` then the :class:`Future` was cancelled,
       i.e. :meth:`Future.cancel` was called and returned `True`.  Any threads
       waiting on the :class:`Future` completing (i.e. through
       :func:`as_completed` or :func:`wait`) will be woken up.

       If the method returns ``True`` then the :class:`Future` was not cancelled
       and has been put in the running state, i.e. calls to
       :meth:`Future.running` will return `True`.

       This method can only be called once and cannot be called after
       :meth:`Future.set_result` or :meth:`Future.set_exception` have been
       called.

    .. method:: set_result(result)

       Sets the result of the work associated with the :class:`Future` to
       *result*.

       This method should only be used by :class:`Executor` implementations and
       unit tests.

    .. method:: set_exception(exception)

       Sets the result of the work associated with the :class:`Future` to the
       :class:`Exception` *exception*.

       This method should only be used by :class:`Executor` implementations and
       unit tests.


Module Functions
----------------

.. function:: wait(fs, timeout=None, return_when=ALL_COMPLETED)

   Wait for the :class:`Future` instances (possibly created by different
   :class:`Executor` instances) given by *fs* to complete.  Returns a named
   2-tuple of sets.  The first set, named ``done``, contains the futures that
   completed (finished or were cancelled) before the wait completed.  The second
   set, named ``not_done``, contains uncompleted futures.

   *timeout* can be used to control the maximum number of seconds to wait before
   returning.  *timeout* can be an int or float.  If *timeout* is not specified
   or ``None``, there is no limit to the wait time.

   *return_when* indicates when this function should return.  It must be one of
   the following constants:

   +-----------------------------+----------------------------------------+
   | Constant                    | Description                            |
   +=============================+========================================+
   | :const:`FIRST_COMPLETED`    | The function will return when any      |
   |                             | future finishes or is cancelled.       |
   +-----------------------------+----------------------------------------+
   | :const:`FIRST_EXCEPTION`    | The function will return when any      |
   |                             | future finishes by raising an          |
   |                             | exception.  If no future raises an     |
   |                             | exception then it is equivalent to     |
   |                             | :const:`ALL_COMPLETED`.                |
   +-----------------------------+----------------------------------------+
   | :const:`ALL_COMPLETED`      | The function will return when all      |
   |                             | futures finish or are cancelled.       |
   +-----------------------------+----------------------------------------+

.. function:: as_completed(fs, timeout=None)

   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
   before :func:`as_completed` is called will be yielded first.  The returned
   iterator raises a :exc:`TimeoutError` if :meth:`__next__` is called and the
   result isn't available after *timeout* seconds from the original call to
   :func:`as_completed`.  *timeout* can be an int or float.  If *timeout* is not
   specified or ``None``, there is no limit to the wait time.


.. seealso::

   :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

