{"id":3490,"date":"2022-05-14T03:50:41","date_gmt":"2022-05-14T03:50:41","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=3490"},"modified":"2022-07-15T03:48:50","modified_gmt":"2022-07-15T03:48:50","slug":"python-threadpoolexecutor","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/python-concurrency\/python-threadpoolexecutor\/","title":{"rendered":"Python ThreadPoolExecutor"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to use the Python <code>ThreadPoolExecutor<\/code> to develop multi-threaded programs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-python-threadpoolexecutor-class'>Introduction to the Python ThreadPoolExecutor class <a href=\"#introduction-to-the-python-threadpoolexecutor-class\" class=\"anchor\" id=\"introduction-to-the-python-threadpoolexecutor-class\" title=\"Anchor for Introduction to the Python ThreadPoolExecutor class\">#<\/a><\/h2>\n\n\n\n<p><a href=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-threading\/\">In the multithreading tutorial<\/a>, you learned how to manage multiple threads in a program using the <code>Thread<\/code> class of the <code>threading<\/code> module. The <code>Thread<\/code> class is useful when you want to create threads manually.<\/p>\n\n\n\n<p>However, manually managing threads is not efficient because creating and destroying many threads frequently are very expensive in terms of computational costs. <\/p>\n\n\n\n<p>Instead of doing so, you may want to reuse the threads if you expect to run many ad-hoc tasks in the program. A thread pool allows you to achieve this.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='thread-pool'>Thread pool <a href=\"#thread-pool\" class=\"anchor\" id=\"thread-pool\" title=\"Anchor for Thread pool\">#<\/a><\/h3>\n\n\n\n<p>A thread pool is a pattern for achieving concurrency of execution in a program. A thread pool allows you to automatically manage a pool of threads efficiently:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2022\/05\/Python-ThreadPoolExecutor-Thread-Pool.svg\" alt=\"Python ThreadPoolExecutor Thread Pool\" class=\"wp-image-3507\"\/><\/figure>\n\n\n\n<p>Each thread in the pool is called a worker thread or a worker. A thread pool allows you to reuse the worker threads once the tasks are completed. It also protects against unexpected failures such as <a href=\"https:\/\/www.pythontutorial.net\/python-oop\/python-exceptions\/\">exceptions<\/a>.<\/p>\n\n\n\n<p>Typically, a thread pool allows you to configure the number of worker threads and provides a specific naming convention for each worker thread.<\/p>\n\n\n\n<p>To create a thread pool, you use the <code>ThreadPoolExecutor<\/code> class from the <code>concurrent.futures<\/code> module.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='threadpoolexecutor'>ThreadPoolExecutor <a href=\"#threadpoolexecutor\" class=\"anchor\" id=\"threadpoolexecutor\" title=\"Anchor for ThreadPoolExecutor\">#<\/a><\/h3>\n\n\n\n<p>The <code>ThreadPoolExecutor<\/code> class <a href=\"https:\/\/www.pythontutorial.net\/python-oop\/python-inheritance\/\">extends<\/a> the <code>Executor<\/code> class and returns a <code>Future<\/code> object.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='executor'>Executor <a href=\"#executor\" class=\"anchor\" id=\"executor\" title=\"Anchor for Executor\">#<\/a><\/h3>\n\n\n\n<p>The <code>Executor<\/code> class has three methods to control the thread pool:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code><code>submit()<\/code><\/code> &#8211; dispatch a function to be executed and return a <code>Future<\/code> object. The <code>submit()<\/code> method takes a function and executes it asynchronously. <\/li><li><code>map()<\/code> &#8211; execute a function asynchronously for each element in an iterable.<\/li><li><code>shutdown()<\/code> &#8211; shut down the executor.<\/li><\/ul>\n\n\n\n<p>When you create a new instance of the <code>ThreadPoolExecutor<\/code> class, Python starts the <code>Executor<\/code>. <\/p>\n\n\n\n<p>Once completing working with the executor, you must explicitly call the <code>shutdown()<\/code> method to release the resource held by the executor. To avoid calling the <code>shutdown()<\/code> method explicitly, you can use the <a href=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-context-managers\/\">context manager<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='future-object'>Future object <a href=\"#future-object\" class=\"anchor\" id=\"future-object\" title=\"Anchor for Future object\">#<\/a><\/h3>\n\n\n\n<p>A <code>Future<\/code> is an object that represents the eventual result of an asynchronous operation. The Future class has two useful methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><code>result()<\/code> &#8211; return the result of an asynchronous operation.<\/li><li><code>exception()<\/code> &#8211; return the exception of an asynchronous operation in case an exception occurs.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id='python-threadpoolexecutor-examples'>Python ThreadPoolExecutor examples <a href=\"#python-threadpoolexecutor-examples\" class=\"anchor\" id=\"python-threadpoolexecutor-examples\" title=\"Anchor for Python ThreadPoolExecutor examples\">#<\/a><\/h2>\n\n\n\n<p>The following program uses a single thread:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> time <span class=\"hljs-keyword\">import<\/span> sleep, perf_counter\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(id)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">f'Starting the task <span class=\"hljs-subst\">{id}<\/span>...'<\/span>)\n    sleep(<span class=\"hljs-number\">1<\/span>)\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'Done with task <span class=\"hljs-subst\">{id}<\/span>'<\/span>\n\nstart = perf_counter()\n\nprint(task(<span class=\"hljs-number\">1<\/span>))\nprint(task(<span class=\"hljs-number\">2<\/span>))\n\nfinish = perf_counter()\n\nprint(<span class=\"hljs-string\">f\"It took <span class=\"hljs-subst\">{finish-start}<\/span> second(s) to finish.\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">Starting the task <span class=\"hljs-number\">1.<\/span>..\nDone <span class=\"hljs-keyword\">with<\/span> task <span class=\"hljs-number\">1<\/span>\nStarting the task <span class=\"hljs-number\">2.<\/span>..\nDone <span class=\"hljs-keyword\">with<\/span> task <span class=\"hljs-number\">2<\/span>\nIt took <span class=\"hljs-number\">2.0144479<\/span> second(s) to finish.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, define the <code><code>task()<\/code><\/code> function that takes about one second to finish. The <code><code>task()<\/code><\/code> function calls the <code>sleep()<\/code> function to simulate a delay:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(id)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">f'Starting the task <span class=\"hljs-subst\">{id}<\/span>...'<\/span>)\n    sleep(<span class=\"hljs-number\">1<\/span>)\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'Done with task <span class=\"hljs-subst\">{id}<\/span>'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, call the <code><code>task()<\/code><\/code> function twice and print out the result. Before and after calling the <code><code>task()<\/code><\/code> function, we use the <code>perf_counter()<\/code> to measure the start and finish time:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">start = perf_counter()\n\nprint(task(<span class=\"hljs-number\">1<\/span>))\nprint(task(<span class=\"hljs-number\">2<\/span>))\n\nfinish = perf_counter()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, print out the time the program took to run:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">print(<span class=\"hljs-string\">f\"It took <span class=\"hljs-subst\">{finish-start}<\/span> second(s) to finish.\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Because the <code>task()<\/code> function takes one second, calling it twice will take about 2 seconds. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='using-the-submit-method-example'>Using the submit() method example <a href=\"#using-the-submit-method-example\" class=\"anchor\" id=\"using-the-submit-method-example\" title=\"Anchor for Using the submit() method example\">#<\/a><\/h3>\n\n\n\n<p>To run the <code>task()<\/code> function concurrently, you can use the <code>ThreadPoolExecutor<\/code> class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> time <span class=\"hljs-keyword\">import<\/span> sleep, perf_counter\n<span class=\"hljs-keyword\">from<\/span> concurrent.futures <span class=\"hljs-keyword\">import<\/span> ThreadPoolExecutor\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(id)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">f'Starting the task <span class=\"hljs-subst\">{id}<\/span>...'<\/span>)\n    sleep(<span class=\"hljs-number\">1<\/span>)\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'Done with task <span class=\"hljs-subst\">{id}<\/span>'<\/span>\n\nstart = perf_counter()\n\n<span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:\n    f1 = executor.submit(task, <span class=\"hljs-number\">1<\/span>)\n    f2 = executor.submit(task, <span class=\"hljs-number\">2<\/span>)\n\n    print(f1.result())\n    print(f2.result())    \n\nfinish = perf_counter()\n\nprint(<span class=\"hljs-string\">f\"It took <span class=\"hljs-subst\">{finish-start}<\/span> second(s) to finish.\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">Starting the task <span class=\"hljs-number\">1.<\/span>..\nStarting the task <span class=\"hljs-number\">2.<\/span>..\nDone <span class=\"hljs-keyword\">with<\/span> task <span class=\"hljs-number\">1<\/span>\nDone <span class=\"hljs-keyword\">with<\/span> task <span class=\"hljs-number\">2<\/span>\nIt took <span class=\"hljs-number\">1.0177214<\/span> second(s) to finish.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows that the program took about 1 second to finish.<\/p>\n\n\n\n<p>How it works (we&#8217;ll focus on the thread pool part):<\/p>\n\n\n\n<p>First, import the <code>ThreadPoolExecutor<\/code> class from the <code>concurrent.futures<\/code> module:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> concurrent.futures <span class=\"hljs-keyword\">import<\/span> ThreadPoolExecutor<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, create a thread pool using the <code>ThreadPoolExecutor<\/code> using a context manager:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, calling the <code>task()<\/code> function twice by passing it to the <code>submit()<\/code> method of the executor:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:\n    f1 = executor.submit(task, <span class=\"hljs-number\">1<\/span>)\n    f2 = executor.submit(task, <span class=\"hljs-number\">2<\/span>)\n\n    print(f1.result())\n    print(f2.result()) <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>submit()<\/code> method returns a Future object. In this example, we have two Future objects <code>f1<\/code> and <code>f2<\/code>. To get the result from the Future object, we called its <code>result()<\/code> method.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='using-the-map-method-example'>Using the map() method example <a href=\"#using-the-map-method-example\" class=\"anchor\" id=\"using-the-map-method-example\" title=\"Anchor for Using the map() method example\">#<\/a><\/h3>\n\n\n\n<p>The following program uses a <code>ThreadPoolExecutor<\/code> class. However, instead of using the <code>submit()<\/code> method, it uses the <code>map()<\/code> method to execute a function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> time <span class=\"hljs-keyword\">import<\/span> sleep, perf_counter\n<span class=\"hljs-keyword\">from<\/span> concurrent.futures <span class=\"hljs-keyword\">import<\/span> ThreadPoolExecutor\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">task<\/span><span class=\"hljs-params\">(id)<\/span>:<\/span>\n    print(<span class=\"hljs-string\">f'Starting the task <span class=\"hljs-subst\">{id}<\/span>...'<\/span>)\n    sleep(<span class=\"hljs-number\">1<\/span>)\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'Done with task <span class=\"hljs-subst\">{id}<\/span>'<\/span>\n\nstart = perf_counter()\n\n<span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:\n    results = executor.map(task, &#91;<span class=\"hljs-number\">1<\/span>,<span class=\"hljs-number\">2<\/span>])\n    <span class=\"hljs-keyword\">for<\/span> result <span class=\"hljs-keyword\">in<\/span> results:\n        print(result)\n\nfinish = perf_counter()\n\nprint(<span class=\"hljs-string\">f\"It took <span class=\"hljs-subst\">{finish-start}<\/span> second(s) to finish.\"<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, call the <code><code>map()<\/code><\/code> method of the executor object to run the task function for each id in the list [1,2]. The <code><code>map()<\/code><\/code> method returns an iterator that contains the result of the function calls.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">results = executor.map(task, &#91;<span class=\"hljs-number\">1<\/span>,<span class=\"hljs-number\">2<\/span>])<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, iterate over the results and print them out:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">for<\/span> result <span class=\"hljs-keyword\">in<\/span> results:\n    print(result)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='python-threadpoolexecutor-practical-example'>Python ThreadPoolExecutor practical example <a href=\"#python-threadpoolexecutor-practical-example\" class=\"anchor\" id=\"python-threadpoolexecutor-practical-example\" title=\"Anchor for Python ThreadPoolExecutor practical example\">#<\/a><\/h2>\n\n\n\n<p>The following program downloads multiple images from Wikipedia using a thread pool:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> concurrent.futures <span class=\"hljs-keyword\">import<\/span> ThreadPoolExecutor\n<span class=\"hljs-keyword\">from<\/span> urllib.request <span class=\"hljs-keyword\">import<\/span> urlopen\n<span class=\"hljs-keyword\">import<\/span> time\n<span class=\"hljs-keyword\">import<\/span> os\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">download_image<\/span><span class=\"hljs-params\">(url)<\/span>:<\/span>\n    image_data = <span class=\"hljs-literal\">None<\/span>\n    <span class=\"hljs-keyword\">with<\/span> urlopen(url) <span class=\"hljs-keyword\">as<\/span> f:\n        image_data = f.read()\n\n    <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">not<\/span> image_data:\n        <span class=\"hljs-keyword\">raise<\/span> Exception(<span class=\"hljs-string\">f\"Error: could not download the image from <span class=\"hljs-subst\">{url}<\/span>\"<\/span>)\n\n    filename = os.path.basename(url)\n    <span class=\"hljs-keyword\">with<\/span> open(filename, <span class=\"hljs-string\">'wb'<\/span>) <span class=\"hljs-keyword\">as<\/span> image_file:\n        image_file.write(image_data)\n        print(<span class=\"hljs-string\">f'<span class=\"hljs-subst\">{filename}<\/span> was downloaded...'<\/span>)\n\nstart = time.perf_counter()\n\nurls = &#91;<span class=\"hljs-string\">'https:\/\/upload.wikimedia.org\/wikipedia\/commons\/9\/9d\/Python_bivittatus_1701.jpg'<\/span>,\n        <span class=\"hljs-string\">'https:\/\/upload.wikimedia.org\/wikipedia\/commons\/4\/48\/Python_Regius.jpg'<\/span>,\n        <span class=\"hljs-string\">'https:\/\/upload.wikimedia.org\/wikipedia\/commons\/d\/d3\/Baby_carpet_python_caudal_luring.jpg'<\/span>,\n        <span class=\"hljs-string\">'https:\/\/upload.wikimedia.org\/wikipedia\/commons\/f\/f0\/Rock_python_pratik.JPG'<\/span>,\n        <span class=\"hljs-string\">'https:\/\/upload.wikimedia.org\/wikipedia\/commons\/0\/07\/Dulip_Wilpattu_Python1.jpg'<\/span>]\n\n<span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:\n      executor.map(download_image, urls)\n\nfinish = time.perf_counter()    \n\nprint(<span class=\"hljs-string\">f'It took <span class=\"hljs-subst\">{finish-start}<\/span> second(s) to finish.'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, define a function <code>download_image()<\/code> that downloads an image from an URL and saves it into a file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">download_image<\/span><span class=\"hljs-params\">(url)<\/span>:<\/span>\n    image_data = <span class=\"hljs-literal\">None<\/span>\n    <span class=\"hljs-keyword\">with<\/span> urlopen(url) <span class=\"hljs-keyword\">as<\/span> f:\n        image_data = f.read()\n\n    <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">not<\/span> image_data:\n        <span class=\"hljs-keyword\">raise<\/span> Exception(<span class=\"hljs-string\">f\"Error: could not download the image from <span class=\"hljs-subst\">{url}<\/span>\"<\/span>)\n\n    filename = os.path.basename(url)\n    <span class=\"hljs-keyword\">with<\/span> open(filename, <span class=\"hljs-string\">'wb'<\/span>) <span class=\"hljs-keyword\">as<\/span> image_file:\n        image_file.write(image_data)\n        print(<span class=\"hljs-string\">f'<span class=\"hljs-subst\">{filename}<\/span> was downloaded...'<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>download_image()<\/code> function the <code>urlopen()<\/code> function from the <code>urllib.request<\/code> module to download an image from an URL.<\/p>\n\n\n\n<p>Second, execute the <code>download_image()<\/code> function using a thread pool by calling the <code>map()<\/code> method of the <code>ThreadPoolExecutor<\/code> object:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">with<\/span> ThreadPoolExecutor() <span class=\"hljs-keyword\">as<\/span> executor:\n      executor.map(download_image, urls)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>A thread pool is a pattern for managing multiple threads efficiently.<\/li><li>Use <code>ThreadPoolExecutor<\/code> class to manage a thread pool in Python.<\/li><li>Call the <code><code>submit()<\/code><\/code> method of the <code>ThreadPoolExecutor<\/code> to submit a task to the thread pool for execution. The <code><code>submit()<\/code><\/code> method returns a Future object.<\/li><li>Call the <code>map()<\/code> method of the <code>ThreadPoolExecutor<\/code> class to execute a function in a thread pool with each element in a list.<\/li><\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"3490\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/python-concurrency\/python-threadpoolexecutor\/\"\n\t\t\t\tdata-post-title=\"Python ThreadPoolExecutor\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"3490\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/python-concurrency\/python-threadpoolexecutor\/\"\n\t\t\t\tdata-post-title=\"Python ThreadPoolExecutor\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to use the Python ThreadPoolExecutor to develop multi-threaded programs.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":4104,"menu_order":6,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3490","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/3490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/comments?post=3490"}],"version-history":[{"count":0,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/3490\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/4104"}],"wp:attachment":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/media?parent=3490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}