| |
| <!DOCTYPE html> |
| |
| <html> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" /> |
| |
| <title>User Guide — more-executors documentation</title> |
| <link rel="stylesheet" type="text/css" href="_static/pygments.css" /> |
| <link rel="stylesheet" type="text/css" href="_static/alabaster.css" /> |
| <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> |
| <script src="_static/jquery.js"></script> |
| <script src="_static/underscore.js"></script> |
| <script src="_static/doctools.js"></script> |
| <link rel="index" title="Index" href="genindex.html" /> |
| <link rel="search" title="Search" href="search.html" /> |
| <link rel="next" title="Reference" href="api-reference.html" /> |
| <link rel="prev" title="more-executors" href="index.html" /> |
| |
| <link rel="stylesheet" href="_static/custom.css" type="text/css" /> |
| |
| |
| <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" /> |
| |
| </head><body> |
| |
| |
| <div class="document"> |
| <div class="documentwrapper"> |
| <div class="bodywrapper"> |
| |
| |
| <div class="body" role="main"> |
| |
| <section id="user-guide"> |
| <h1>User Guide<a class="headerlink" href="#user-guide" title="Permalink to this headline">¶</a></h1> |
| <section id="base-executors"> |
| <span id="id1"></span><h2>Base executors<a class="headerlink" href="#base-executors" title="Permalink to this headline">¶</a></h2> |
| <p>These methods on the <code class="xref py py-class docutils literal notranslate"><span class="pre">more_executors.Executors</span></code> class |
| create standalone <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor" title="(in Python v3.11)"><code class="xref py py-class docutils literal notranslate"><span class="pre">Executor</span></code></a> |
| instances which may serve as the basis of <a class="reference internal" href="#composing-executors">composing executors</a>.</p> |
| <blockquote> |
| <div><dl class="simple"> |
| <dt><a class="reference internal" href="reference/base-executors.html#more_executors.Executors.thread_pool" title="more_executors.Executors.thread_pool"><code class="xref py py-meth docutils literal notranslate"><span class="pre">thread_pool()</span></code></a></dt><dd><p>creates a new <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor" title="(in Python v3.11)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadPoolExecutor</span></code></a> |
| to execute callables in threads.</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/base-executors.html#more_executors.Executors.process_pool" title="more_executors.Executors.process_pool"><code class="xref py py-meth docutils literal notranslate"><span class="pre">process_pool()</span></code></a></dt><dd><p>creates a new <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor" title="(in Python v3.11)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ProcessPoolExecutor</span></code></a> |
| to execute callables in processes.</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/base-executors.html#more_executors.Executors.sync" title="more_executors.Executors.sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">sync()</span></code></a></dt><dd><p>creates a new <a class="reference internal" href="reference/base-executors.html#more_executors.SyncExecutor" title="more_executors.SyncExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">SyncExecutor</span></code></a> |
| to execute callables in the calling thread.</p> |
| </dd> |
| </dl> |
| </div></blockquote> |
| <p>Example:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">more_executors</span> <span class="kn">import</span> <span class="n">Executors</span> |
| <span class="k">with</span> <span class="n">Executors</span><span class="o">.</span><span class="n">thread_pool</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'web-client'</span><span class="p">)</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span> |
| <span class="n">future</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="n">submit</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">,</span> <span class="s1">'https://github.com/rohanpm/more-executors'</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| </section> |
| <section id="composing-executors"> |
| <span id="id2"></span><h2>Composing executors<a class="headerlink" href="#composing-executors" title="Permalink to this headline">¶</a></h2> |
| <p>Executors produced by this module can be customized by chaining a series of |
| <cite>with_*</cite> methods. This may be used to compose different behaviors for specific |
| use-cases.</p> |
| <p>Methods for composition are provided for all implemented executors:</p> |
| <blockquote> |
| <div><dl class="simple"> |
| <dt><a class="reference internal" href="reference/futures-map.html#more_executors.Executors.with_map" title="more_executors.Executors.with_map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_map()</span></code></a></dt><dd><p>transform the output of a future, synchronously</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/futures-map.html#more_executors.Executors.with_flat_map" title="more_executors.Executors.with_flat_map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_flat_map()</span></code></a></dt><dd><p>transform the output of a future, asynchronously</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/retry.html#more_executors.Executors.with_retry" title="more_executors.Executors.with_retry"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_retry()</span></code></a></dt><dd><p>retry failing futures</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/poll.html#more_executors.Executors.with_poll" title="more_executors.Executors.with_poll"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_poll()</span></code></a></dt><dd><p>resolve futures via a custom poll function</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/timeout.html#more_executors.Executors.with_timeout" title="more_executors.Executors.with_timeout"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_timeout()</span></code></a></dt><dd><p>cancel unresolved futures after a timeout</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/throttle.html#more_executors.Executors.with_throttle" title="more_executors.Executors.with_throttle"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_throttle()</span></code></a></dt><dd><p>limit the number of concurrently executing futures</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/cancel.html#more_executors.Executors.with_cancel_on_shutdown" title="more_executors.Executors.with_cancel_on_shutdown"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_cancel_on_shutdown()</span></code></a></dt><dd><p>cancel any pending futures on executor shutdown</p> |
| </dd> |
| <dt><a class="reference internal" href="reference/asyncio.html#more_executors.Executors.with_asyncio" title="more_executors.Executors.with_asyncio"><code class="xref py py-meth docutils literal notranslate"><span class="pre">with_asyncio()</span></code></a></dt><dd><p>bridge between <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#module-concurrent.futures" title="(in Python v3.11)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">concurrent.futures</span></code></a> and <a class="reference external" href="https://docs.python.org/3/library/asyncio.html#module-asyncio" title="(in Python v3.11)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a></p> |
| </dd> |
| </dl> |
| </div></blockquote> |
| <p>Example:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Run in up to 4 threads, retry on failure, transform output values</span> |
| <span class="n">executor</span> <span class="o">=</span> <span class="n">Executors</span><span class="o">.</span><span class="n">thread_pool</span><span class="p">(</span><span class="n">max_workers</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">'web-client'</span><span class="p">)</span><span class="o">.</span> \ |
| <span class="n">with_map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">response</span><span class="p">:</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">())</span><span class="o">.</span> \ |
| <span class="n">with_retry</span><span class="p">()</span> |
| <span class="n">responses</span> <span class="o">=</span> <span class="p">[</span><span class="n">executor</span><span class="o">.</span><span class="n">submit</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">,</span> <span class="n">url</span><span class="p">)</span> |
| <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">urls</span><span class="p">]</span> |
| </pre></div> |
| </div> |
| <p>Keep in mind that the order in which executors are composed is significant. |
| For example, these two composition sequences have different effects:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">Executors</span><span class="o">.</span><span class="n">sync</span><span class="p">()</span><span class="o">.</span><span class="n">with_retry</span><span class="p">()</span><span class="o">.</span><span class="n">with_throttle</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>In this example, if 4 callables have failed and retries are currently pending, |
| throttling takes effect, and any additional callables will be enqueued until at |
| least one of the earlier callables has completed (or exhausted all retry |
| attempts).</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">Executors</span><span class="o">.</span><span class="n">sync</span><span class="p">()</span><span class="o">.</span><span class="n">with_throttle</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span><span class="o">.</span><span class="n">with_retry</span><span class="p">()</span> |
| </pre></div> |
| </div> |
| <p>In this example, an unlimited number of futures may be failed and awaiting |
| retries. The throttling in this example has no effect, since a |
| <a class="reference internal" href="reference/base-executors.html#more_executors.SyncExecutor" title="more_executors.SyncExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">SyncExecutor</span></code></a> is intrinsically throttled to |
| a single pending future.</p> |
| </section> |
| <section id="naming-executors"> |
| <span id="id3"></span><h2>Naming executors<a class="headerlink" href="#naming-executors" title="Permalink to this headline">¶</a></h2> |
| <p>All executors accept an optional <code class="docutils literal notranslate"><span class="pre">name</span></code> argument, an arbitrary string. |
| Setting the <code class="docutils literal notranslate"><span class="pre">name</span></code> when creating an executor has the following effects:</p> |
| <ul class="simple"> |
| <li><p>If the executor creates any threads, the thread name will include the |
| specified value.</p></li> |
| <li><p>The name will be used as <code class="docutils literal notranslate"><span class="pre">executor</span></code> label on any <a class="reference internal" href="#metrics"><span class="std std-ref">Prometheus metrics</span></a> |
| associated with the executor.</p></li> |
| </ul> |
| <p>When creating chained executors via the <code class="docutils literal notranslate"><span class="pre">with_*</span></code> methods |
| (see <a class="reference internal" href="#composing-executors"><span class="std std-ref">Composing executors</span></a>), names automatically propagate through |
| the chain:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">Executors</span><span class="o">.</span><span class="n">thread_pool</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">'svc-client'</span><span class="p">)</span><span class="o">.</span><span class="n">with_retry</span><span class="p">()</span><span class="o">.</span><span class="n">with_throttle</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>In the above example, three executors are created and all of them are |
| given the name <code class="docutils literal notranslate"><span class="pre">svc-client</span></code>.</p> |
| </section> |
| <section id="composing-futures"> |
| <h2>Composing futures<a class="headerlink" href="#composing-futures" title="Permalink to this headline">¶</a></h2> |
| <p>A series of functions are provided for creating and composing |
| <code class="xref py py-class docutils literal notranslate"><span class="pre">Future</span></code> objects. These functions |
| may be used standalone, or in conjunction with the Executor |
| implementations in <code class="docutils literal notranslate"><span class="pre">more-executors</span></code>.</p> |
| <table class="docutils align-default"> |
| <colgroup> |
| <col style="width: 29%" /> |
| <col style="width: 46%" /> |
| <col style="width: 25%" /> |
| </colgroup> |
| <thead> |
| <tr class="row-odd"><th class="head"><p>Function</p></th> |
| <th class="head"><p>Signature</p></th> |
| <th class="head"><p>Description</p></th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-create.html#more_executors.f_return" title="more_executors.f_return"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_return()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>X</dt><dd><p>⟶ Future<X></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>wrap any value in a future</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/futures-create.html#more_executors.f_return_error" title="more_executors.f_return_error"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_return_error()</span></code></a></p></td> |
| <td><p><cite>n/a</cite></p></td> |
| <td><p>wrap any exception in a future</p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-create.html#more_executors.f_return_cancelled" title="more_executors.f_return_cancelled"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_return_cancelled()</span></code></a></p></td> |
| <td><p><cite>n/a</cite></p></td> |
| <td><p>get a cancelled future</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/futures-apply.html#more_executors.f_apply" title="more_executors.f_apply"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_apply()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<fn<A[,B[,…]]⟶R>>, Future<A>[, Future<B>[, …]]</dt><dd><p>⟶ Future<R></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>apply a function in the future</p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-bool.html#more_executors.f_or" title="more_executors.f_or"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_or()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<A>[, Future<B>[, …]]</dt><dd><p>⟶ Future<A|B|…></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>boolean <code class="docutils literal notranslate"><span class="pre">OR</span></code></p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/futures-bool.html#more_executors.f_and" title="more_executors.f_and"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_and()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<A>[, Future<B>[, …]]</dt><dd><p>⟶ Future<A|B|…></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>boolean <code class="docutils literal notranslate"><span class="pre">AND</span></code></p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-lists.html#more_executors.f_zip" title="more_executors.f_zip"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_zip()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<A>[, Future<B>[, …]]</dt><dd><p>⟶ Future<A[, B[, …]]></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>combine futures into a tuple</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/futures-map.html#more_executors.f_map" title="more_executors.f_map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_map()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<A>, fn<A⟶B></dt><dd><p>⟶ Future<B></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>transform output value of a future |
| via a blocking function</p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-map.html#more_executors.f_flat_map" title="more_executors.f_flat_map"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_flat_map()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<A>, fn<A⟶Future<B>></dt><dd><p>⟶ Future<B></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>transform output value of a future |
| via a non-blocking function</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/futures-lists.html#more_executors.f_traverse" title="more_executors.f_traverse"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_traverse()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>fn<A⟶Future<B>>, iterable<A></dt><dd><p>⟶ Future<list<B>></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>run non-blocking function over |
| iterable</p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-lists.html#more_executors.f_sequence" title="more_executors.f_sequence"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_sequence()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>list<Future<X>></dt><dd><p>⟶ Future<list<X>></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>convert list of futures to a future |
| of list</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/cancel.html#more_executors.f_nocancel" title="more_executors.f_nocancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_nocancel()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<X></dt><dd><p>⟶ Future<X></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>make a future unable to be cancelled</p></td> |
| </tr> |
| <tr class="row-even"><td><p><a class="reference internal" href="reference/futures-proxy.html#more_executors.f_proxy" title="more_executors.f_proxy"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_proxy()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<X></dt><dd><p>⟶ Future<X></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>make a future proxy calls to the |
| future’s result</p></td> |
| </tr> |
| <tr class="row-odd"><td><p><a class="reference internal" href="reference/timeout.html#more_executors.f_timeout" title="more_executors.f_timeout"><code class="xref py py-meth docutils literal notranslate"><span class="pre">f_timeout()</span></code></a></p></td> |
| <td><dl class="simple"> |
| <dt>Future<X>, float</dt><dd><p>⟶ Future<X></p> |
| </dd> |
| </dl> |
| </td> |
| <td><p>make a future cancel itself after a |
| timeout has elapsed</p></td> |
| </tr> |
| </tbody> |
| </table> |
| </section> |
| <section id="usage-of-threads"> |
| <h2>Usage of threads<a class="headerlink" href="#usage-of-threads" title="Permalink to this headline">¶</a></h2> |
| <p>Several executors internally make use of threads. Thus, executors should be |
| considered relatively heavyweight: creating dozens of executors within a |
| process is probably fine, creating thousands is possibly not.</p> |
| <p>Callbacks added by <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future.add_done_callback" title="(in Python v3.11)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_done_callback()</span></code></a> may |
| be invoked from any thread and should avoid any slow blocking operations.</p> |
| <p>All provided executors are thread-safe with the exception of the |
| <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.shutdown" title="(in Python v3.11)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a> method, which should be called |
| from one thread only.</p> |
| </section> |
| <section id="executor-shutdown"> |
| <h2>Executor shutdown<a class="headerlink" href="#executor-shutdown" title="Permalink to this headline">¶</a></h2> |
| <p>Shutting down an executor will also shut down all wrapped executors.</p> |
| <p>In the example below, any threads created by the |
| <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor" title="(in Python v3.11)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadPoolExecutor</span></code></a>, as well as the thread |
| created by the <a class="reference internal" href="reference/retry.html#more_executors.RetryExecutor" title="more_executors.RetryExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">RetryExecutor</span></code></a>, will be joined |
| at the end of the <cite>with</cite> block:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">executor</span> <span class="o">=</span> <span class="n">Executors</span><span class="o">.</span><span class="n">thread_pool</span><span class="p">()</span><span class="o">.</span> \ |
| <span class="n">with_map</span><span class="p">(</span><span class="n">check_result</span><span class="p">)</span><span class="o">.</span> \ |
| <span class="n">with_retry</span><span class="p">()</span> |
| |
| <span class="k">with</span> <span class="n">executor</span><span class="p">:</span> |
| <span class="n">do_something</span><span class="p">(</span><span class="n">executor</span><span class="p">)</span> |
| <span class="n">do_other_thing</span><span class="p">(</span><span class="n">executor</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>Note this implies that sharing of executors needs to be done carefully. |
| For example, this code is broken:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">executor</span> <span class="o">=</span> <span class="n">Executors</span><span class="o">.</span><span class="n">thread_pool</span><span class="p">()</span><span class="o">.</span><span class="n">with_map</span><span class="p">(</span><span class="n">check_result</span><span class="p">)</span> |
| |
| <span class="c1"># Only need retries on this part</span> |
| <span class="k">with</span> <span class="n">executor</span><span class="o">.</span><span class="n">with_retry</span><span class="p">()</span> <span class="k">as</span> <span class="n">retry_executor</span><span class="p">:</span> |
| <span class="n">do_flaky_something</span><span class="p">(</span><span class="n">retry_executor</span><span class="p">)</span> |
| |
| <span class="c1"># BUG: don't do this!</span> |
| <span class="c1"># The thread pool executor was already shut down, so this won't work.</span> |
| <span class="k">with</span> <span class="n">executor</span><span class="p">:</span> |
| <span class="n">do_something</span><span class="p">(</span><span class="n">executor</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>Generally, shutting down executors is optional and is not necessary to |
| (eventually) reclaim resources.</p> |
| <p>However, where executors accept caller-provided code (such as the polling |
| function to <a class="reference internal" href="reference/poll.html#more_executors.PollExecutor" title="more_executors.PollExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">PollExecutor</span></code></a> or the retry |
| policy to <a class="reference internal" href="reference/retry.html#more_executors.RetryExecutor" title="more_executors.RetryExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">RetryExecutor</span></code></a>), it is easy to |
| accidentally create a circular reference between the provided code and the |
| executor. When this happens, it will no longer be possible for the garbage |
| collector to clean up the executor’s resources automatically and a thread |
| leak may occur. If in doubt, call |
| <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.shutdown" title="(in Python v3.11)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a>.</p> |
| </section> |
| <section id="prometheus-metrics"> |
| <span id="metrics"></span><h2>Prometheus metrics<a class="headerlink" href="#prometheus-metrics" title="Permalink to this headline">¶</a></h2> |
| <p>This library automatically collects <a class="reference external" href="https://prometheus.io/">Prometheus</a> |
| metrics if the <code class="docutils literal notranslate"><span class="pre">prometheus_client</span></code> Python module is available. |
| The feature is disabled when this module is not installed or if the |
| <code class="docutils literal notranslate"><span class="pre">MORE_EXECUTORS_PROMETHEUS</span></code> environment variable is set to <code class="docutils literal notranslate"><span class="pre">0</span></code>.</p> |
| <p>If you want to ensure that <code class="docutils literal notranslate"><span class="pre">more-executors</span></code> is installed along with |
| all prometheus dependencies, you may request the ‘prometheus’ extras, |
| as in example:</p> |
| <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">more</span><span class="o">-</span><span class="n">executors</span><span class="p">[</span><span class="n">prometheus</span><span class="p">]</span> |
| </pre></div> |
| </div> |
| <p>The library only collects metrics; it does not expose them. |
| You must use <code class="docutils literal notranslate"><span class="pre">prometheus_client</span></code> to expose metrics in the most |
| appropriate manner when integrating this library with your tool or service. |
| Here is a simple example to dump metrics to a file:</p> |
| <div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">prometheus_client</span> |
| <span class="n">prometheus_client</span><span class="o">.</span><span class="n">write_to_textfile</span><span class="p">(</span><span class="s1">'metrics.txt'</span><span class="p">)</span> |
| </pre></div> |
| </div> |
| <p>The following metrics are available:</p> |
| <blockquote> |
| <div><dl> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_exec_inprogress</span></code></dt><dd><p>A <em>gauge</em> for the number of executors currently in use.</p> |
| <p>“In use” means an executor has been created and <code class="docutils literal notranslate"><span class="pre">shutdown()</span></code> not |
| yet called. Incorrect usage of <code class="docutils literal notranslate"><span class="pre">shutdown()</span></code> (e.g. calling more than |
| once) will lead to inaccurate data.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_exec_total</span></code></dt><dd><p>A <em>counter</em> for the total number of executors created.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_future_inprogress</span></code></dt><dd><p>A <em>gauge</em> for the number of futures currently in progress.</p> |
| <p>“In progress” means a future has been created and not yet reached |
| a terminal state.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_future_total</span></code></dt><dd><p>A <em>counter</em> for the total number of futures created.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_future_cancel_total</span></code></dt><dd><p>A <em>counter</em> for the total number of futures cancelled.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_future_error_total</span></code></dt><dd><p>A <em>counter</em> for the total number of futures resolved with an exception.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_future_time_total</span></code></dt><dd><p>A <em>counter</em> for the total execution time (in seconds) of futures.</p> |
| <p>The execution time of a future is the period between the |
| creation and resolution of a future.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_poll_total</span></code></dt><dd><p>A <em>counter</em> for the total number of times a <a class="reference internal" href="reference/poll.html#poll-function"><span class="std std-ref">Poll function</span></a> was |
| invoked.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_poll_error_total</span></code></dt><dd><p>A <em>counter</em> for the total number of times a <a class="reference internal" href="reference/poll.html#poll-function"><span class="std std-ref">Poll function</span></a> |
| raised an exception.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_poll_time_total</span></code></dt><dd><p>A <em>counter</em> for the total execution time (in seconds) of |
| <a class="reference internal" href="reference/poll.html#poll-function"><span class="std std-ref">Poll function</span></a> calls.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_retry_total</span></code></dt><dd><p>A <em>counter</em> for the total number of times a future was retried |
| by <a class="reference internal" href="reference/retry.html#more_executors.RetryExecutor" title="more_executors.RetryExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">RetryExecutor</span></code></a>.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_retry_queue</span></code></dt><dd><p>A <em>gauge</em> for the current queue size of a |
| <a class="reference internal" href="reference/retry.html#more_executors.RetryExecutor" title="more_executors.RetryExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">RetryExecutor</span></code></a> (i.e. the |
| number of futures currently waiting to retry).</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_retry_delay_total</span></code></dt><dd><p>A <em>counter</em> for the total time (in seconds) spent waiting to |
| retry futures via <a class="reference internal" href="reference/retry.html#more_executors.RetryExecutor" title="more_executors.RetryExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">RetryExecutor</span></code></a>.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_throttle_queue</span></code></dt><dd><p>A <em>gauge</em> for the current queue size of a |
| <a class="reference internal" href="reference/throttle.html#more_executors.ThrottleExecutor" title="more_executors.ThrottleExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">ThrottleExecutor</span></code></a> (i.e. the number of futures |
| not yet able to start due to throttling).</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_timeout_total</span></code></dt><dd><p>A <em>counter</em> for the total number of futures cancelled due to timeout |
| via <a class="reference internal" href="reference/timeout.html#more_executors.TimeoutExecutor" title="more_executors.TimeoutExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">TimeoutExecutor</span></code></a> or |
| <a class="reference internal" href="reference/timeout.html#more_executors.f_timeout" title="more_executors.f_timeout"><code class="xref py py-func docutils literal notranslate"><span class="pre">f_timeout()</span></code></a>.</p> |
| <p>Only successfully cancelled futures are included.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">more_executors_shutdown_cancel_total</span></code></dt><dd><p>A <em>counter</em> for the total number of futures cancelled due to executor |
| shutdown via <a class="reference internal" href="reference/cancel.html#more_executors.CancelOnShutdownExecutor" title="more_executors.CancelOnShutdownExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">CancelOnShutdownExecutor</span></code></a>.</p> |
| <p>Only successfully cancelled futures are included.</p> |
| </dd> |
| </dl> |
| </div></blockquote> |
| <p>Metrics include the following labels:</p> |
| <blockquote> |
| <div><dl> |
| <dt><code class="docutils literal notranslate"><span class="pre">type</span></code></dt><dd><p>The type of executor or future in use; e.g. <code class="docutils literal notranslate"><span class="pre">map</span></code>, <code class="docutils literal notranslate"><span class="pre">retry</span></code>, |
| <code class="docutils literal notranslate"><span class="pre">poll</span></code>.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">executor</span></code></dt><dd><p>Name of executor (see <a class="reference internal" href="#naming-executors"><span class="std std-ref">Naming executors</span></a>).</p> |
| <p>Executors created for internal use by this library are named |
| <code class="docutils literal notranslate"><span class="pre">internal</span></code>.</p> |
| </dd> |
| </dl> |
| </div></blockquote> |
| </section> |
| </section> |
| |
| |
| </div> |
| |
| </div> |
| </div> |
| <div class="sphinxsidebar" role="navigation" aria-label="main navigation"> |
| <div class="sphinxsidebarwrapper"> |
| <h1 class="logo"><a href="index.html">more-executors</a></h1> |
| |
| |
| |
| <p class="blurb">A library of composable Python executors and futures</p> |
| |
| |
| |
| |
| |
| |
| |
| |
| <h3>Navigation</h3> |
| <p class="caption" role="heading"><span class="caption-text">Contents:</span></p> |
| <ul class="current"> |
| <li class="toctree-l1 current"><a class="current reference internal" href="#">User Guide</a><ul> |
| <li class="toctree-l2"><a class="reference internal" href="#base-executors">Base executors</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#composing-executors">Composing executors</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#naming-executors">Naming executors</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#composing-futures">Composing futures</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#usage-of-threads">Usage of threads</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#executor-shutdown">Executor shutdown</a></li> |
| <li class="toctree-l2"><a class="reference internal" href="#prometheus-metrics">Prometheus metrics</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="api-reference.html">Reference</a></li> |
| </ul> |
| |
| |
| <hr /> |
| <ul> |
| |
| <li class="toctree-l1"><a href="https://github.com/rohanpm/more-executors">Source</a></li> |
| |
| <li class="toctree-l1"><a href="https://pypi.python.org/pypi/more-executors">PyPI</a></li> |
| |
| </ul> |
| <div class="relations"> |
| <h3>Related Topics</h3> |
| <ul> |
| <li><a href="index.html">Documentation overview</a><ul> |
| <li>Previous: <a href="index.html" title="previous chapter">more-executors</a></li> |
| <li>Next: <a href="api-reference.html" title="next chapter">Reference</a></li> |
| </ul></li> |
| </ul> |
| </div> |
| <div id="searchbox" style="display: none" role="search"> |
| <h3 id="searchlabel">Quick search</h3> |
| <div class="searchformwrapper"> |
| <form class="search" action="search.html" method="get"> |
| <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/> |
| <input type="submit" value="Go" /> |
| </form> |
| </div> |
| </div> |
| <script>$('#searchbox').show(0);</script> |
| |
| |
| |
| |
| |
| |
| |
| |
| </div> |
| </div> |
| <div class="clearer"></div> |
| </div> |
| <div class="footer"> |
| ©2021, Rohan McGovern. |
| |
| | |
| <a href="_sources/user-guide.rst.txt" |
| rel="nofollow">Page source</a> |
| </div> |
| |
| |
| <a href="https://github.com/rohanpm/more-executors" class="github"> |
| <img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" class="github"/> |
| </a> |
| |
| |
| |
| </body> |
| </html> |