{"id":290,"date":"2024-01-27T14:09:03","date_gmt":"2024-01-27T14:09:03","guid":{"rendered":"https:\/\/learnpython.elegantwallp.com\/?p=290"},"modified":"2024-01-27T14:09:06","modified_gmt":"2024-01-27T14:09:06","slug":"python-threading","status":"publish","type":"post","link":"https:\/\/learnpython.elegantwallp.com\/2024\/01\/27\/python-threading\/","title":{"rendered":"Python Threading"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you\u2019ll learn how to use the Python threading module to develop multi-threaded applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Single-threaded applications<\/h2>\n\n\n\n<p>Let\u2019s start with a simple program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from time import sleep, perf_counter def task(): print('Starting a task...') sleep(1) print('done') start_time = perf_counter() task() task() end_time = perf_counter() print(f'It took {end_time- start_time: 0.2f} second(s) to complete.') <\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, import the\u00a0<code>sleep()<\/code>\u00a0and\u00a0<code>perf_counter()<\/code>\u00a0functions from the\u00a0<code>time<\/code>\u00a0module:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from time import sleep, perf_counter<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Second,\u00a0define a function\u00a0that takes one second to complete:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>def task(): print('Starting a task...') sleep(1) print('done')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Third, get the value of the performance counter by calling the\u00a0<code>perf_counter()<\/code>\u00a0function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>start_time = perf_counter() <\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Fourth, call the\u00a0<code>task()<\/code>\u00a0function twice:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>task() task()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Fifth, get the value of the performance counter by calling the\u00a0<code>perf_counter()<\/code>\u00a0function:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>end_time = perf_counter()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Finally, output the time that takes to complete running the\u00a0<code>task()<\/code>\u00a0function twice:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>print(f'It took {end_time- start_time: 0.2f} second(s) to complete.')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Here is the output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>Starting a task... done Starting a task... done It took 2.00 second(s) to complete.<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>As you may expect, the program takes about two seconds to complete. If you call the&nbsp;<code>task()<\/code>&nbsp;function 10 times, it would take about 10 seconds to complete.<\/p>\n\n\n\n<p>The following diagram illustrates how the program works:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2020\/12\/Python-Threading-Single-threaded-App.png\" alt=\"\" class=\"wp-image-1701\"\/><\/figure>\n\n\n\n<p>First, the&nbsp;<code>task()<\/code>&nbsp;function executes and sleeps for one second. Then it executes the second time and also sleeps for another second. Finally, the program completes.<\/p>\n\n\n\n<p>When the&nbsp;<code>task()<\/code>&nbsp;function calls the&nbsp;<code>sleep()<\/code>&nbsp;function, the CPU is idle. In other words, the CPU doesn\u2019t do anything, which is not efficient in terms of resource utilization.<\/p>\n\n\n\n<p>This program has one process with a single thread, which is called the&nbsp;<strong>main thread<\/strong>. Because the program has only one thread, it\u2019s called a single-threaded program.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using Python threading to develop a multi-threaded program example<\/h2>\n\n\n\n<p>To create a multi-threaded program, you need to use the Python&nbsp;<code>threading<\/code>&nbsp;module.<\/p>\n\n\n\n<p>First, import the&nbsp;<code>Thread<\/code>&nbsp;class from the&nbsp;<code>threading<\/code>&nbsp;module:<code>from threading import Thread<\/code><small>Code language: Python (python)<\/small><\/p>\n\n\n\n<p>Second, create a new thread by instantiating an instance of the\u00a0<code>Thread<\/code>\u00a0class:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>new_thread = Thread(target=fn,args=args_tuple)<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The&nbsp;<code>Thread()<\/code>&nbsp;accepts many parameters. The main ones are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>target<\/code>: specifies a function (<code>fn<\/code>) to run in the new thread.<\/li>\n\n\n\n<li><code>args<\/code>: specifies the arguments of the function (<code>fn<\/code>). The&nbsp;<code>args<\/code>&nbsp;argument is a tuple.<\/li>\n<\/ul>\n\n\n\n<p>Third, start the thread by calling the\u00a0<code>start()<\/code>\u00a0method of the\u00a0<code>Thread<\/code>\u00a0instance:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>new_thread.start()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>If you want to wait for the thread to complete in the main thread, you can call the\u00a0<code>join()<\/code>\u00a0method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>new_thread.join()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>By calling the&nbsp;<code>join()<\/code>&nbsp;method, the main thread will wait for the child thread to complete before it is terminated.<\/p>\n\n\n\n<p>The following program illustrates how to use the\u00a0<code>threading<\/code>\u00a0module:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from time import sleep, perf_counter from threading import Thread def task(): print('Starting a task...') sleep(1) print('done') start_time = perf_counter() <em># create two new threads<\/em> t1 = Thread(target=task) t2 = Thread(target=task) <em># start the threads<\/em> t1.start() t2.start() <em># wait for the threads to complete<\/em> t1.join() t2.join() end_time = perf_counter() print(f'It took {end_time- start_time: 0.2f} second(s) to complete.')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>How it works. (and we\u2019ll focus on the threading part only)<\/p>\n\n\n\n<p>First, create two new threads:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>t1 = Thread(target=task) t2 = Thread(target=task)<\/code><\/code><\/pre>\n\n\n\n<p>Second, start both threads by calling the\u00a0<code>start()<\/code>\u00a0method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>t1.start() t2.start()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Third, wait for both threads to complete:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>t1.join() t2.join()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Finally, show the executing time:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>print(f'It took {end_time- start_time: 0.2f} second(s) to complete.')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>Starting a task... Starting a task... done done It took 1.00 second(s) to complete.<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>When the program executes, it\u2019ll have three threads: the main thread and two other child threads.<\/p>\n\n\n\n<p>As shown clearly from the output, the program took one second instead of two to complete.<\/p>\n\n\n\n<p>The following diagram shows how threads execute:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/www.pythontutorial.net\/wp-content\/uploads\/2020\/12\/Python-Threading-Multi-threaded-App.png\" alt=\"\" class=\"wp-image-1702\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Passing arguments to threads<\/h2>\n\n\n\n<p>The following program shows how to pass arguments to the function assigned to a thread:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from time import sleep, perf_counter from threading import Thread def task(id): print(f'Starting the task {id}...') sleep(1) print(f'The task {id} completed') start_time = perf_counter() <em># create and start 10 threads<\/em> threads = &#91;] for n in range(1, 11): t = Thread(target=task, args=(n,)) threads.append(t) t.start() <em># wait for the threads to complete<\/em> for t in threads: t.join() end_time = perf_counter() print(f'It took {end_time- start_time: 0.2f} second(s) to complete.')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, define a\u00a0<code>task()<\/code>\u00a0function that accepts an argument:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>def task(id): print(f'Starting the task {id}...') sleep(1) print(f'The task {id} completed')<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Second, create 10 new threads and pass an id to each. The\u00a0<code>threads<\/code>\u00a0list is used to keep track of all newly created threads:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>threads = &#91;] for n in range(1, 11): t = Thread(target=task, args=(n,)) threads.append(t) t.start()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Notice that if you call the&nbsp;<code>join()<\/code>&nbsp;method inside the loop, the program will wait for the first thread to complete before starting the next one.<\/p>\n\n\n\n<p>Third, wait for all threads to complete by calling the\u00a0<code>join()<\/code>\u00a0method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>for t in threads: t.join()<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following shows the output of the program:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>Starting the task 1... Starting the task 2... Starting the task 3... Starting the task 4... Starting the task 5... Starting the task 6... Starting the task 7... Starting the task 8... Starting the task 9... Starting the task 10... The task 10 completed The task 8 completed The task 1 completed The task 6 completed The task 7 completed The task 9 completed The task 3 completed The task 4 completed The task 2 completed The task 5 completed It took 1.02 second(s) to complete.<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>It just took 1.05 seconds to complete.<\/p>\n\n\n\n<p>Notice that the program doesn\u2019t execute the thread in the order from 1 to 10.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">When to use Python threading<\/h2>\n\n\n\n<p>As introduced in the\u00a0process and thread tutorial, there\u2019re two main kinds of tasks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I\/O-bound tasks \u2013 the time spent on I\/O is significantly more than the time spent on computation.<\/li>\n\n\n\n<li>CPU-bound tasks \u2013 the time spent on computation is significantly higher than the time waiting for I\/O.<\/li>\n<\/ul>\n\n\n\n<p>Python threading is optimized for I\/O bound tasks. For example, requesting remote resources, connecting a database server, or reading and writing files.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Practical Python threading example<\/h2>\n\n\n\n<p>Suppose that you have a list of text files in a folder e.g.,&nbsp;<code>C:\/temp\/<\/code>. And you want to replace a text with a new one in all the files.<\/p>\n\n\n\n<p>The following single-threaded program shows how to replace a substring with the new one in the text files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from time import perf_counter def replace(filename, substr, new_substr): print(f'Processing the file {filename}') <em># get the contents of the file<\/em> with open(filename, 'r') as f: content = f.read() <em># replace the substr by new_substr<\/em> content = content.replace(substr, new_substr) <em># write data into the file<\/em> with open(filename, 'w') as f: f.write(content) def main(): filenames = &#91; 'c:\/temp\/test1.txt', 'c:\/temp\/test2.txt', 'c:\/temp\/test3.txt', 'c:\/temp\/test4.txt', 'c:\/temp\/test5.txt', 'c:\/temp\/test6.txt', 'c:\/temp\/test7.txt', 'c:\/temp\/test8.txt', 'c:\/temp\/test9.txt', 'c:\/temp\/test10.txt', ] for filename in filenames: replace(filename, 'ids', 'id') if __name__ == \"__main__\": start_time = perf_counter() main() end_time = perf_counter() print(f'It took {end_time- start_time :0.2f} second(s) to complete.') <\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>It took 0.16 second(s) to complete.<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>The following program has the same functionality. However, it uses multiple threads instead:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>from threading import Thread from time import perf_counter def replace(filename, substr, new_substr): print(f'Processing the file {filename}') <em># get the contents of the file<\/em> with open(filename, 'r') as f: content = f.read() <em># replace the substr by new_substr<\/em> content = content.replace(substr, new_substr) <em># write data into the file<\/em> with open(filename, 'w') as f: f.write(content) def main(): filenames = &#91; 'c:\/temp\/test1.txt', 'c:\/temp\/test2.txt', 'c:\/temp\/test3.txt', 'c:\/temp\/test4.txt', 'c:\/temp\/test5.txt', 'c:\/temp\/test6.txt', 'c:\/temp\/test7.txt', 'c:\/temp\/test8.txt', 'c:\/temp\/test9.txt', 'c:\/temp\/test10.txt', ] <em># create threads<\/em> threads = &#91;Thread(target=replace, args=(filename, 'id', 'ids')) for filename in filenames] <em># start the threads<\/em> for thread in threads: thread.start() <em># wait for the threads to complete<\/em> for thread in threads: thread.join() if __name__ == \"__main__\": start_time = perf_counter() main() end_time = perf_counter() print(f'It took {end_time- start_time :0.2f} second(s) to complete.') <\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>Processing the file c:\/temp\/test1.txt Processing the file c:\/temp\/test2.txt Processing the file c:\/temp\/test3.txt Processing the file c:\/temp\/test4.txt Processing the file c:\/temp\/test5.txt Processing the file c:\/temp\/test6.txt Processing the file c:\/temp\/test7.txt Processing the file c:\/temp\/test8.txt Processing the file c:\/temp\/test9.txt Processing the file c:\/temp\/test10.txt It took 0.02 second(s) to complete.<\/code><small>Code language: Python (python)<\/small><\/code><\/pre>\n\n\n\n<p>As you can see clearly from the output, the multi-threaded program runs so much faster.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: in this tutorial, you\u2019ll learn how to use the Python threading module to develop multi-threaded applications. Single-threaded applications Let\u2019s start with a simple program: How it works. First, import the\u00a0sleep()\u00a0and\u00a0perf_counter()\u00a0functions from the\u00a0time\u00a0module: Second,\u00a0define a function\u00a0that takes one second to complete: Third, get the value of the performance counter by calling the\u00a0perf_counter()\u00a0function: Fourth, call the\u00a0task()\u00a0function [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[],"class_list":["post-290","post","type-post","status-publish","format-standard","hentry","category-1-python-concurrency"],"_links":{"self":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/comments?post=290"}],"version-history":[{"count":1,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/290\/revisions"}],"predecessor-version":[{"id":291,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/posts\/290\/revisions\/291"}],"wp:attachment":[{"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/media?parent=290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/categories?post=290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnpython.elegantwallp.com\/wp-json\/wp\/v2\/tags?post=290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}