<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Pragati Verma</title>
    <description>The latest articles on Forem by Pragati Verma (@pragativerma18).</description>
    <link>https://forem.com/pragativerma18</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242611%2F3cef560b-1c27-403a-ac74-76260a792597.jpg</url>
      <title>Forem: Pragati Verma</title>
      <link>https://forem.com/pragativerma18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pragativerma18"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Thu, 20 Mar 2025 13:09:48 +0000</pubDate>
      <link>https://forem.com/pragativerma18/-487i</link>
      <guid>https://forem.com/pragativerma18/-487i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/pragativerma18" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242611%2F3cef560b-1c27-403a-ac74-76260a792597.jpg" alt="pragativerma18"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/pragativerma18/understanding-pythons-garbage-collection-and-memory-optimization-4mi2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Understanding Python's Garbage Collection and Memory Optimization&lt;/h2&gt;
      &lt;h3&gt;Pragati Verma ・ Mar 17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#codenewbie&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>programming</category>
      <category>python</category>
      <category>computerscience</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Understanding Python's Garbage Collection and Memory Optimization</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Mon, 17 Mar 2025 12:47:35 +0000</pubDate>
      <link>https://forem.com/pragativerma18/understanding-pythons-garbage-collection-and-memory-optimization-4mi2</link>
      <guid>https://forem.com/pragativerma18/understanding-pythons-garbage-collection-and-memory-optimization-4mi2</guid>
      <description>&lt;p&gt;Memory management is one of the most important yet underestimated aspects of programming. Most developers focus on features and functionality, often neglecting this hidden foundation until problems arise. Poor memory management leads to programs that run slowly, crash without warning, or gradually consume more memory until they fail. &lt;/p&gt;

&lt;p&gt;However, unlike other programming languages such as C, C++ and Java, where developers must allocate and deallocate memory explicitly, Python automates this process using &lt;strong&gt;Reference Counting&lt;/strong&gt; and &lt;strong&gt;Garbage Collection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we will discuss Python's memory management system in depth. We'll start with how Python organizes memory, then understand reference counting and its limitations, and finally discuss how garbage collection solves these problems.&lt;/p&gt;

&lt;p&gt;Here's an overview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Python organizes memory (stack memory and heap memory)&lt;/li&gt;
&lt;li&gt;Python's primary memory management: Reference counting&lt;/li&gt;
&lt;li&gt;Limitations of reference counting&lt;/li&gt;
&lt;li&gt;Python's garbage collection system&lt;/li&gt;
&lt;li&gt;Practical strategies for memory optimization&lt;/li&gt;
&lt;li&gt;Real-world applications and performance considerations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before learning about how Python tracks and cleans up memory, it's essential to understand how memory is structured. Let's start with the fundamentals of how Python organizes memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Organization in Python
&lt;/h2&gt;

&lt;p&gt;To handle memory allocation effectively, Python organizes memory into two main regions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stack Memory&lt;/strong&gt;: This stores function calls, local variables, and control flow. It is automatically managed, with memory being allocated and freed as functions execute.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Heap Memory&lt;/strong&gt;: This is used for dynamically allocated objects such as lists, dictionaries, and user-defined instances. These objects remain in memory until they are no longer needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3u0v8r0g2zfw9780og1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3u0v8r0g2zfw9780og1.png" alt="Stack memory vs Heap memory" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack Memory
&lt;/h3&gt;

&lt;p&gt;Stack memory handles function calls, local variables, and references to objects. Each time a function is called, a new stack frame is created, storing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function arguments&lt;/li&gt;
&lt;li&gt;Local variables (names referencing objects)&lt;/li&gt;
&lt;li&gt;Control flow information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the function completes, the stack frame is discarded, and its references are removed.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# 'x' is stored in stack memory
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# 'result' now references the returned list
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;x&lt;/code&gt; exists in the stack memory during function execution, but the list &lt;code&gt;[10, 20, 30]&lt;/code&gt; is created in heap memory. When the function returns, &lt;code&gt;x&lt;/code&gt; is removed from the stack, but since &lt;code&gt;result&lt;/code&gt; still references the list, it remains in heap memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heap Memory
&lt;/h3&gt;

&lt;p&gt;All dynamically allocated objects (lists, dictionaries, user-defined objects) are stored in heap memory. As long as references exist, these objects persist beyond function execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# The list is created in heap memory
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;p&gt;The list &lt;code&gt;[5, 6, 7]&lt;/code&gt; resides in heap memory and the name &lt;code&gt;x&lt;/code&gt; is stored in stack memory and acts as a reference to the heap object&lt;/p&gt;

&lt;p&gt;Now that we understand how memory is organized let's examine how Python keeps track of these heap objects by counting references.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python's Primary Memory Management: Reference Counting
&lt;/h2&gt;

&lt;p&gt;In many programming languages, such as C, C++, and Java, variables and objects are distinct - variables directly store values or memory addresses pointing to objects. However, in Python, variables are merely names (labels) that reference objects in memory rather than storing values themselves. Python uses &lt;strong&gt;reference counting&lt;/strong&gt; to track how many names point to a given object, as multiple names can reference the same object.&lt;/p&gt;

&lt;p&gt;Each object in Python consists of three key attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: The object's data type is inferred automatically by Python&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt;: The actual data stored within the object&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference Count&lt;/strong&gt;: The number of references (or names) pointing to the object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12h8hffak87vu3xfwmpj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12h8hffak87vu3xfwmpj.png" alt="Integer Object in Python" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python provides a &lt;a href="https://docs.python.org/3/library/sys.html" rel="noopener noreferrer"&gt;&lt;code&gt;sys.getrefcount()&lt;/code&gt;&lt;/a&gt; function that can be used to check an object's reference count:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# Output: 2 (one for 'a', one for function argument)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The count is &lt;strong&gt;2&lt;/strong&gt; because calling &lt;code&gt;sys.getrefcount(a)&lt;/code&gt; temporarily creates another reference as a function argument.&lt;/p&gt;

&lt;p&gt;The reference count increases each time a new reference is created and decreases every time a reference is deleted or reassigned. &lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Reference count: 1
&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;          &lt;span class="c1"&gt;# Reference count: 2 (both 'a' and 'b' reference the same list)
&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;       &lt;span class="c1"&gt;# Reference count: 1 (only 'b' references the list now)
&lt;/span&gt;&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;          &lt;span class="c1"&gt;# Reference count: 0 (no references left)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an object's reference count drops to zero, Python automatically deallocates the memory, making it available for future use. This automatic cleanup is a significant advantage of Python's memory management system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Reference Counting
&lt;/h3&gt;

&lt;p&gt;Reference counting offers several benefits as a memory management strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immediate Cleanup&lt;/strong&gt; – When an object's reference count reaches zero, it is deallocated instantly, preventing excessive memory consumption.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt; – The mechanism is straightforward and does not require complex background processes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deterministic Behavior&lt;/strong&gt; – Since objects are freed as soon as they become unreferenced, we can predict when memory will be released.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, despite these advantages, reference counting alone is insufficient for comprehensive memory management. Let's examine its limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of Reference Counting
&lt;/h3&gt;

&lt;p&gt;While reference counting efficiently handles most memory management scenarios, it has several significant limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Overhead&lt;/strong&gt;: Incrementing and decrementing reference counts adds a small but constant performance cost, especially in large applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Thread-Safe&lt;/strong&gt;: Reference counting can cause issues in multi-threaded programs due to potential race conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Circular References&lt;/strong&gt;: The biggest limitation is that objects referencing each other keep their reference count above zero, preventing automatic deallocation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem of circular references deserves special attention. &lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  &lt;span class="c1"&gt;# 'a' references 'b'
&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;  &lt;span class="c1"&gt;# 'b' references 'a'
&lt;/span&gt;
&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  &lt;span class="c1"&gt;# Objects still exist due to circular reference
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, even after deleting the variables &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, the Node objects themselves continue to exist in memory because they reference each other, keeping their reference counts at 1 instead of 0. This creates a memory leak that reference counting alone cannot resolve.&lt;/p&gt;

&lt;p&gt;Thus, the circular reference problem represents a fundamental limitation of reference counting that requires an additional mechanism to resolve. This is where Python's garbage collection system comes into play as a complementary solution to reference counting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python's Garbage Collection System
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.python.org/3/library/gc.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Garbage collection (GC)&lt;/strong&gt;&lt;/a&gt; is Python's complementary memory management system that works alongside reference counting to clean up objects no longer in use, particularly those involved in circular references. It frees memory allocated to unused objects, preventing memory leaks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generational Garbage Collection
&lt;/h3&gt;

&lt;p&gt;Python's GC follows a generational approach to optimize performance. The idea is that most objects have short lifespans, so collecting them frequently improves efficiency. &lt;/p&gt;

&lt;p&gt;The garbage collector divides objects into three generations based on their age:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generation 0 (Youngest)&lt;/strong&gt;: Newly created objects. Collected most frequently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation 1 (Intermediate Age)&lt;/strong&gt;: Objects that survived a previous collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation 2 (Oldest)&lt;/strong&gt;: Long-lived objects, such as global variables and cached data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F162o1l5jedqpihj485n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F162o1l5jedqpihj485n1.png" alt="Three generations of objects based on their age." width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How Garbage Collection Works Step by Step
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Starts with Generation 0 (Youngest Objects)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When garbage collection runs, it first checks Generation 0, which contains the newest objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since short-lived objects (e.g., temporary variables in functions) are most likely to become garbage quickly, this step helps free memory efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Objects That Survive Are Promoted&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If an object is still referenced after a collection, it is moved to the next generation (Generation 1) instead of being deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This means Python assumes that if an object has survived one garbage collection, it might be needed for a longer period.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, objects in Generation 1 that survive another collection are promoted to Generation 2.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Generation 2 (Long-Lived Objects) Is Collected Least Often&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since objects in Generation 2 have already survived multiple collections, Python assumes they are important and unlikely to be garbage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As a result, Generation 2 is collected the least frequently, reducing performance overhead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Examples of such objects include module-level variables, global caches, and persistent data structures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftnmqv0xnmm06doxmw6gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftnmqv0xnmm06doxmw6gy.png" alt="Garbage Collection Process" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This incremental collection prevents unnecessary performance overhead while keeping memory usage efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detecting and Breaking Circular References
&lt;/h2&gt;

&lt;p&gt;Python's garbage collector periodically scans memory to find objects that mutually reference each other but are no longer accessible from the rest of the program. &lt;/p&gt;

&lt;p&gt;Here's how it works with our previous example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;

&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;  &lt;span class="c1"&gt;# Objects still exist due to circular reference
&lt;/span&gt;
&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Manually trigger garbage collection
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, calling &lt;code&gt;gc.collect()&lt;/code&gt; forces Python to scan for circular references. The garbage collector identifies that the two Node objects form a reference cycle that's no longer accessible from the program and removes them, freeing up memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Does Garbage Collection Run?
&lt;/h2&gt;

&lt;p&gt;Python's garbage collector automatically runs in the background based on a threshold system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A collection cycle is triggered if the number of object allocations exceeds a set limit.&lt;/li&gt;
&lt;li&gt;Developers can manually trigger garbage collection using &lt;a href="https://docs.python.org/3/library/gc.html#gc.collect" rel="noopener noreferrer"&gt;&lt;code&gt;gc.collect()&lt;/code&gt;&lt;/a&gt;, though this is rarely needed.&lt;/li&gt;
&lt;li&gt;The garbage collector can also be disabled with &lt;a href="https://docs.python.org/3/library/gc.html#gc.disable" rel="noopener noreferrer"&gt;&lt;code&gt;gc.disable()&lt;/code&gt;&lt;/a&gt; if performance optimization is required in specific cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While reference counting handles most memory deallocation immediately, the garbage collector provides a safety net that catches circular references and other complex memory issues that reference counting cannot address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;While Python's GC system is generally efficient, frequent garbage collection cycles can cause minor performance slowdowns, especially in memory-intensive applications. &lt;/p&gt;

&lt;p&gt;We can also fine-tune collection behavior using the &lt;code&gt;gc&lt;/code&gt; module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust thresholds using &lt;a href="https://docs.python.org/3/library/gc.html#gc.set_threshold" rel="noopener noreferrer"&gt;&lt;code&gt;gc.set_threshold()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Monitor collection statistics with &lt;a href="https://docs.python.org/3/library/gc.html#gc.get_stats" rel="noopener noreferrer"&gt;&lt;code&gt;gc.get_stats()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Disable automatic collection in performance-critical sections and run it manually.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we understand Python's memory management, let's look at practical strategies for optimizing memory usage in your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing Memory Management in Python
&lt;/h2&gt;

&lt;p&gt;While Python's garbage collection system handles memory cleanup automatically, unoptimized memory usage can lead to performance bottlenecks. &lt;/p&gt;

&lt;p&gt;The following strategies help in managing memory more efficiently:&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoiding Unnecessary Object Creation
&lt;/h3&gt;

&lt;p&gt;Creating too many objects unnecessarily increases memory usage and strains Python's garbage collector. Using memory-efficient techniques, such as generators instead of lists, can significantly reduce memory consumption.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Using Generators Instead of Lists
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# List consumes memory for all elements at once
&lt;/span&gt;&lt;span class="n"&gt;squares_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;  

&lt;span class="c1"&gt;# Generator computes values on demand, reducing memory usage
&lt;/span&gt;&lt;span class="n"&gt;squares_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since generators yield values one at a time, they prevent storing large lists in memory, making them ideal for iterating over large datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Circular References Efficiently
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Circular references&lt;/em&gt; occur when objects reference each other, preventing reference counts from reaching zero. While Python's cyclic garbage collector detects and cleans up these objects, using weak references can help break reference cycles and optimize memory usage.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Using Weak References to Prevent Cycles
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;weakref&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;weak_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weakref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Creates a weak reference instead of a strong one
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike normal references, weak references do not increase the reference count. Once an object has no strong references left, it is automatically garbage-collected, even if weak references point to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disabling or Controlling Garbage Collection When Necessary
&lt;/h3&gt;

&lt;p&gt;In high-performance applications (such as real-time systems or machine learning workloads), automatic garbage collection may cause performance overhead. Disabling it temporarily and running manual collections at controlled intervals can help.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Disabling Garbage Collection
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gc&lt;/span&gt;

&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Disable automatic garbage collection
&lt;/span&gt;
&lt;span class="c1"&gt;# Perform high-performance operations...
&lt;/span&gt;
&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Manually trigger garbage collection when needed
&lt;/span&gt;&lt;span class="n"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;# Re-enable automatic garbage collection
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach is useful when frequent GC cycles disrupt performance-sensitive operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring Memory Usage
&lt;/h3&gt;

&lt;p&gt;Tracking memory allocation helps identify leaks and optimize memory usage. Python provides tools like &lt;a href="https://docs.python.org/3/library/tracemalloc.html" rel="noopener noreferrer"&gt;&lt;code&gt;tracemalloc&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/mgedmin/objgraph" rel="noopener noreferrer"&gt;&lt;code&gt;objgraph&lt;/code&gt;&lt;/a&gt; to monitor memory usage effectively.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Using &lt;code&gt;tracemalloc&lt;/code&gt; to Track Memory Usage
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tracemalloc&lt;/span&gt;

&lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Code execution
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_traced_memory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# Shows current and peak memory usage
&lt;/span&gt;
&lt;span class="n"&gt;tracemalloc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By analyzing memory snapshots, developers can identify and optimise objects consuming excessive memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Applications
&lt;/h2&gt;

&lt;p&gt;Understanding Python's memory management becomes particularly important in several scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Processing Applications
&lt;/h3&gt;

&lt;p&gt;When working with large datasets, efficient memory management can be the difference between a functional application and one that crashes due to memory errors. Techniques like generators, chunking data, and processing in batches can significantly reduce the memory footprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long-Running Services
&lt;/h3&gt;

&lt;p&gt;Even small memory leaks can accumulate over time and cause failures for server applications and microservices that run continuously. Regular profiling and monitoring of memory usage help identify and fix these issues early.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource-Constrained Environments
&lt;/h3&gt;

&lt;p&gt;In environments with limited memory (embedded systems, serverless functions with tight memory limits), understanding how Python manages memory allows developers to write more efficient code and avoid hitting resource limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Python's memory management system offers immediate cleanup through reference counting and comprehensive leak prevention through garbage collection. This dual approach ensures that memory is used efficiently with minimal manual intervention from developers.&lt;/p&gt;

&lt;p&gt;However, relying solely on automatic memory management isn't always optimal. Understanding how Python handles memory allows us to write more efficient, high-performing applications.&lt;/p&gt;

&lt;p&gt;By minimizing unnecessary object creation, using weak references, controlling garbage collection, and monitoring memory usage, we can prevent excessive memory consumption and improve application performance. Thoughtful memory management is not just about avoiding leaks but more about writing scalable, optimized code.&lt;/p&gt;

&lt;p&gt;Next time when you debug a memory issue or optimize a Python application, remember how the underlying memory management works. These insights can help you make better design decisions and create more efficient software.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>python</category>
      <category>computerscience</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Setting Up Apache Kafka Locally: A Step-by-Step Guide</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Tue, 21 Jan 2025 16:30:47 +0000</pubDate>
      <link>https://forem.com/pragativerma18/setting-up-apache-kafka-locally-a-step-by-step-guide-2p8</link>
      <guid>https://forem.com/pragativerma18/setting-up-apache-kafka-locally-a-step-by-step-guide-2p8</guid>
      <description>&lt;p&gt;The &lt;a href="https://dev.to/pragativerma18/mastering-apache-kafka-powering-modern-data-pipelines-5ebh"&gt;previous article&lt;/a&gt; explored Apache Kafka’s key features, architecture and real-world applications.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/pragativerma18" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242611%2F3cef560b-1c27-403a-ac74-76260a792597.jpg" alt="pragativerma18"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/pragativerma18/mastering-apache-kafka-powering-modern-data-pipelines-5ebh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mastering Apache Kafka: Powering Modern Data Pipelines&lt;/h2&gt;
      &lt;h3&gt;Pragati Verma ・ Jan 16&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In this article, we’ll walk through the steps to set up Apache Kafka on your local machine. By the end, you'll have a fully functional Kafka environment to start experimenting with data streams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites:
&lt;/h3&gt;

&lt;p&gt;Before we start, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java 8&lt;/strong&gt; or later (Kafka is built on Java)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Homebrew&lt;/strong&gt; (macOS package manager)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Install Kafka Using Homebrew
&lt;/h2&gt;

&lt;p&gt;Homebrew simplifies the installation of Kafka and its dependencies. Open your terminal and run the following commands:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Zookeeper&lt;/strong&gt; (required by Kafka):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;zookeeper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install &lt;strong&gt;Kafka&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;kafka
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install Kafka along with its dependencies, including Zookeeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Start Zookeeper
&lt;/h2&gt;

&lt;p&gt;Kafka depends on Zookeeper for distributed coordination. You need to start Zookeeper first.&lt;/p&gt;

&lt;p&gt;In your terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zkServer start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leave this terminal window open, as Zookeeper will need to keep running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Start Kafka Server
&lt;/h2&gt;

&lt;p&gt;Now that Zookeeper is running, let’s start the Kafka server.&lt;/p&gt;

&lt;p&gt;In a new terminal window, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kafka-server-start /usr/local/etc/kafka/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts the Kafka server on the default port (9092).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create a Kafka Topic
&lt;/h2&gt;

&lt;p&gt;Kafka organizes data into topics. Let’s create a simple topic for testing.&lt;/p&gt;

&lt;p&gt;Run the following command in a new terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kafka-topics &lt;span class="nt"&gt;--create&lt;/span&gt; &lt;span class="nt"&gt;--topic&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092 &lt;span class="nt"&gt;--partitions&lt;/span&gt; 1 &lt;span class="nt"&gt;--replication-factor&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a topic called test with one partition and one replica.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Produce Messages to the Topic
&lt;/h2&gt;

&lt;p&gt;To send messages to the test topic, start a producer session. In a new terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kafka-console-producer &lt;span class="nt"&gt;--broker-list&lt;/span&gt; localhost:9092 &lt;span class="nt"&gt;--topic&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can type messages and press Enter to send them to the test topic.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Hello, Kafka!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Consume Messages from the Topic
&lt;/h2&gt;

&lt;p&gt;Start a consumer session to see the messages you sent to the test topic. Open another terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kafka-console-consumer &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092 &lt;span class="nt"&gt;--topic&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--from-beginning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the messages appear as they are consumed from the test topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Hello, Kafka!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Verify Everything is Running
&lt;/h2&gt;

&lt;p&gt;Congrats! You’ve successfully set up Kafka and tested it locally on your macOS machine. You can now explore more Kafka features, such as Producers, Consumers, and Consumer Groups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Experiment Further
&lt;/h2&gt;

&lt;p&gt;Send more messages through the producer and watch them appear in the consumer.&lt;/p&gt;

&lt;p&gt;Start multiple consumers for the same topic to see how Kafka distributes messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Troubleshooting Tips
&lt;/h2&gt;

&lt;p&gt;Setting up Apache Kafka can sometimes present challenges, especially for beginners. Here are a few common issues and troubleshooting tips to help ensure a smooth setup:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Kafka Broker Won't Start:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: If the Kafka broker fails to start and you see errors related to binding to the port (e.g., Port 9092 is already in use), this usually means that the default Kafka port is occupied by another process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if any other process is using port 9092 by running &lt;code&gt;netstat -an | find "9092"&lt;/code&gt; (Windows) or &lt;code&gt;lsof -i :9092&lt;/code&gt; (Linux/Mac).&lt;/li&gt;
&lt;li&gt;If so, either stop the conflicting process or change the Kafka port in the &lt;code&gt;config/server.properties&lt;/code&gt; file by modifying the &lt;code&gt;listeners&lt;/code&gt; property:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nv"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;PLAINTEXT://localhost:9093
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Zookeeper Not Starting:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: When starting Zookeeper, you might see errors like Failed to bind to &lt;code&gt;/0.0.0.0:2181&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that no other service is using port &lt;code&gt;2181&lt;/code&gt;, which is Zookeeper’s default port.&lt;/li&gt;
&lt;li&gt;Check that the Zookeeper data directory is correctly configured in &lt;code&gt;zookeeper.properties&lt;/code&gt;. If the directory does not exist or is incorrect, create or specify the correct directory.&lt;/li&gt;
&lt;li&gt;Try clearing the Zookeeper data directory (&lt;code&gt;zookeeper-data&lt;/code&gt;) and then restart Zookeeper.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Kafka Producer Cannot Connect to Broker:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: The producer might fail to connect to the broker, throwing errors like &lt;code&gt;Broker not available&lt;/code&gt; or &lt;code&gt;Connection refused&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify that Kafka is running by checking the logs. Look for entries like &lt;code&gt;Started Kafka server&lt;/code&gt; to confirm it's operational.&lt;/li&gt;
&lt;li&gt;Ensure the &lt;code&gt;bootstrap-server&lt;/code&gt; parameter in your producer command points to the correct broker and port. If you changed the default port, update it in your producer configuration.&lt;/li&gt;
&lt;li&gt;Make sure your Kafka server is accessible from the machine where you're running the producer. If you're running Kafka on a different machine, ensure that the network connection and firewall rules allow communication.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Kafka Consumer Not Receiving Messages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: The consumer might not display any messages even though the producer is sending them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check that the consumer is subscribed to the correct topic. You can use the &lt;code&gt;kafka-topics&lt;/code&gt; command to verify that the topic exists:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;indows&lt;span class="se"&gt;\k&lt;/span&gt;afka-topics.bat &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ensure the consumer is consuming from the correct partition, especially in topics with multiple partitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If using multiple consumers, make sure they are properly consuming messages from the topic. Kafka consumers in the same consumer group will share message processing load. If there are fewer partitions than consumers, some consumers might not receive any messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the &lt;code&gt;--from-beginning&lt;/code&gt; flag is used if you want the consumer to read from the start of the topic (not just the latest messages).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Topic Creation Failures:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: When trying to create a topic, you might see an error like The broker does not have a topic with the specified name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that your Kafka broker is running correctly and that you have access to the specified &lt;code&gt;bootstrap-server&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check if the topic already exists using the &lt;code&gt;kafka-topics&lt;/code&gt; command:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;indows&lt;span class="se"&gt;\k&lt;/span&gt;afka-topics.bat &lt;span class="nt"&gt;--describe&lt;/span&gt; &lt;span class="nt"&gt;--topic&lt;/span&gt; MyTopic &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If needed, delete the topic and recreate it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;indows&lt;span class="se"&gt;\k&lt;/span&gt;afka-topics.bat &lt;span class="nt"&gt;--delete&lt;/span&gt; &lt;span class="nt"&gt;--topic&lt;/span&gt; MyTopic &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Kafka Consumer Groups Not Working Properly:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: Kafka consumer groups may not function as expected, with some consumers not processing messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure that each consumer in the group is reading from a different partition. If the topic has more partitions than consumers, the consumers will balance the load, but there may be idle consumers.&lt;/li&gt;
&lt;li&gt;Monitor consumer lag using the &lt;code&gt;kafka-consumer-groups&lt;/code&gt; command:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;indows&lt;span class="se"&gt;\k&lt;/span&gt;afka-consumer-groups.bat &lt;span class="nt"&gt;--describe&lt;/span&gt; &lt;span class="nt"&gt;--group&lt;/span&gt; &amp;lt;consumer-group-name&amp;gt; &lt;span class="nt"&gt;--bootstrap-server&lt;/span&gt; localhost:9092
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Zookeeper and Kafka Version Mismatch:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: Version incompatibility issues between Kafka and Zookeeper may arise when using a newer Kafka version with an older version of Zookeeper or vice versa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure that both Zookeeper and Kafka are compatible. If you're using Kafka 2.8.0 or higher and planning to use KRaft mode, you don’t need Zookeeper anymore. Otherwise, ensure that both components are using compatible versions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By following these troubleshooting steps and tips, most common Kafka setup issues can be resolved quickly, enabling smooth operation of the Kafka ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up Apache Kafka locally can seem challenging due to the various components involved, but with careful configuration and troubleshooting, it becomes manageable. &lt;/p&gt;

&lt;p&gt;By understanding common errors and their resolutions, you can ensure a smooth setup process. Once Kafka is up and running, it unlocks a powerful platform for handling real-time data streams, enabling you to explore features like producers, consumers, and topic management.&lt;/p&gt;

&lt;p&gt;This foundation prepares you to integrate Kafka into your projects and explore advanced use cases. With practice, you’ll master its potential for building scalable, distributed systems that handle massive data flows seamlessly.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>database</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Are you curious about how modern systems handle massive amounts of real-time data? Apache Kafka is the secret behind seamless data streams, from powering stock market analytics to real-time social media insights. Start your Kafka journey today!</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Mon, 20 Jan 2025 14:09:06 +0000</pubDate>
      <link>https://forem.com/pragativerma18/are-you-curious-about-how-modern-systems-handle-massive-amounts-of-real-time-data-apache-kafka-is-3o1b</link>
      <guid>https://forem.com/pragativerma18/are-you-curious-about-how-modern-systems-handle-massive-amounts-of-real-time-data-apache-kafka-is-3o1b</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/pragativerma18" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242611%2F3cef560b-1c27-403a-ac74-76260a792597.jpg" alt="pragativerma18"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/pragativerma18/mastering-apache-kafka-powering-modern-data-pipelines-5ebh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mastering Apache Kafka: Powering Modern Data Pipelines&lt;/h2&gt;
      &lt;h3&gt;Pragati Verma ・ Jan 16&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>kafka</category>
      <category>data</category>
      <category>eventdriven</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Mastering Apache Kafka: Powering Modern Data Pipelines</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Thu, 16 Jan 2025 12:33:50 +0000</pubDate>
      <link>https://forem.com/pragativerma18/mastering-apache-kafka-powering-modern-data-pipelines-5ebh</link>
      <guid>https://forem.com/pragativerma18/mastering-apache-kafka-powering-modern-data-pipelines-5ebh</guid>
      <description>&lt;p&gt;Imagine Uber tracking millions of rides every minute, and each ride generates tons of data, such as driver location, passenger requests, and real-time traffic conditions. Traditional databases struggle to handle such a high-speed data influx, causing slowdowns, inconsistencies, and delays. This is where &lt;a href="https://kafka.apache.org/" rel="noopener noreferrer"&gt;Kafka&lt;/a&gt; saves the day, enabling real-time data streaming that ensures seamless processing at scale.&lt;/p&gt;

&lt;p&gt;In this article, we will get an in-depth understanding of Apache Kafka’s architecture, its key components, and the reasons why it is indispensable for real-time data streaming. By the end, you will gain insights into Kafka’s powerful capabilities and how it addresses challenges that traditional databases are often ill-equipped to handle.&lt;/p&gt;

&lt;p&gt;So, let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Apache Kafka?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzot27zufmtqzo78pv3ul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzot27zufmtqzo78pv3ul.png" alt="Apache Kafka" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kafka was originally developed by LinkedIn in 2010 to address the challenges it faced with its growing data pipeline. The need for a reliable, high-throughput messaging system that could handle real-time data led to the creation of Kafka. In 2011, it was open-sourced, and since then, it has grown in popularity, becoming a central component in many organizations' data infrastructures.&lt;/p&gt;

&lt;p&gt;It is an open-source, distributed event streaming platform that handles large volumes of real-time data. It allows applications to publish, subscribe to, store, and process streams of records, making it ideal for scenarios that require high-speed data handling and real-time analytics.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Apache Kafka was named after &lt;a href="https://en.wikipedia.org/wiki/Franz_Kafka" rel="noopener noreferrer"&gt;Franz Kafka&lt;/a&gt;, the Czech writer known for exploring complex and overwhelming systems in his works. The name reflects Kafka's design to handle massive, intricate data streams, like navigating chaotic systems in Kafka's literature, offering a structured and reliable solution to complex data challenges.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Key Features of Apache Kafka:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: Kafka is designed to scale horizontally, allowing organizations to handle growing data volumes effortlessly. It can be distributed across multiple machines to ensure that even massive datasets are processed smoothly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fault Tolerance&lt;/strong&gt;: Kafka is built to withstand system failures. It replicates data across multiple brokers, ensuring that if one broker fails, another can take over without data loss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Low Latency&lt;/strong&gt;: Kafka provides real-time data streaming with minimal delays, making it ideal for applications that require up-to-the-second data processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Throughput&lt;/strong&gt;: Kafka is optimized for handling high-throughput data streams. It can process millions of records per second, making it suitable for use cases that rapidly generate a large amount of data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Use Apache Kafka?
&lt;/h2&gt;

&lt;p&gt;Unlike traditional message brokers or ETL(Extracting-Transforming-Loading) tools, Kafka manages continuous, high-volume data streams with low latency while providing a fault-tolerant, scalable architecture. &lt;/p&gt;

&lt;p&gt;Traditional systems often struggle with maintaining performance at scale or processing real-time data efficiently, whereas Kafka is specifically designed for these challenges.&lt;/p&gt;

&lt;p&gt;Here's a comparison table highlighting the differences between Apache Kafka and traditional message brokers or ETL tools:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Apache Kafka&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Traditional Message Brokers / ETL Tools&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time stream processing&lt;/td&gt;
&lt;td&gt;Typically batch-oriented or slower messaging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Horizontally scalable with distributed architecture&lt;/td&gt;
&lt;td&gt;Often limited in scaling capabilities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fault Tolerance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in data replication and durability&lt;/td&gt;
&lt;td&gt;Limited fault tolerance, often relies on external systems for backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low latency (real-time processing)&lt;/td&gt;
&lt;td&gt;Higher latency, especially in batch processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High throughput, capable of handling millions of messages per second&lt;/td&gt;
&lt;td&gt;May struggle with high-volume data at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can process both stream and batch data&lt;/td&gt;
&lt;td&gt;Often optimized for either batch or real-time, not both&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real-time analytics, IoT, event-driven architectures&lt;/td&gt;
&lt;td&gt;Messaging, batch processing, and simpler integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Persistent storage of data streams&lt;/td&gt;
&lt;td&gt;Generally does not store data for long durations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Having understood where Kafka can be helpful and should be used, let's look at its core components next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Components of Apache Kafka
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcm9buckn7lx8yleqf23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcm9buckn7lx8yleqf23.png" alt="Core Components of Apache Kafka" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Topics:
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;topic&lt;/strong&gt; is a logical channel to which Kafka producers send data and from which consumers read data. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each message in Kafka belongs to a specific topic, and topics act as the primary mechanism for organizing and categorizing data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Partitions:
&lt;/h3&gt;

&lt;p&gt;Each topic in Kafka can be divided into &lt;strong&gt;partitions&lt;/strong&gt;, which are the basic units of parallelism and scalability. &lt;/p&gt;

&lt;p&gt;Partitions allow Kafka to distribute the load across multiple brokers, enabling the system to handle large volumes of data. &lt;/p&gt;

&lt;p&gt;Each &lt;strong&gt;partition&lt;/strong&gt; is an ordered, immutable sequence of messages, and messages within a partition are assigned a unique offset.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Producers:
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;producer&lt;/strong&gt; is any application or service that sends data to Kafka topics. &lt;/p&gt;

&lt;p&gt;Producers push data to topics, typically in the form of messages or events, and they can write to one or more partitions within those topics.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Consumers:
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;consumer&lt;/strong&gt; is any application or service that reads data from Kafka topics. &lt;/p&gt;

&lt;p&gt;Consumers subscribe to one or more topics and can consume messages from one or more partitions. Multiple consumers can work in parallel to handle high throughput.&lt;/p&gt;

&lt;p&gt;But imagine a system processing thousands of real-time orders every second. A single consumer would quickly become overwhelmed, leading to delays and failures. This is where we have consumer groups.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;consumer group&lt;/strong&gt; is a group of consumers that work together to read data from a topic. Kafka automatically balances the workload among consumers in a group by assigning each partition to one consumer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If a topic has multiple partitions, a consumer group can have multiple consumers reading from those partitions in parallel, which speeds up data processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If one consumer in the group fails, Kafka reassigns its partition to another consumer in the group, ensuring continuous processing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Brokers:
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;broker&lt;/strong&gt; is a Kafka server that stores and serves data. Kafka clusters consist of multiple brokers, with each broker managing a subset of partitions. Brokers store messages and ensure data replication and fault tolerance.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Zookeeper:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://zookeeper.apache.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Zookeeper&lt;/strong&gt;&lt;/a&gt; is a distributed coordination service used in older versions of Kafka to manage cluster metadata, leader election, and configuration. It ensures consistency and synchronization across Kafka brokers. &lt;/p&gt;

&lt;p&gt;However, with the introduction of &lt;a href="https://developer.confluent.io/learn/kraft/" rel="noopener noreferrer"&gt;&lt;strong&gt;KRaft (Kafka Raft)&lt;/strong&gt;&lt;/a&gt; mode, Kafka is gradually moving towards eliminating the reliance on Zookeeper. KRaft allows Kafka to manage metadata directly, simplifying the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Message Flow in Kafka
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Producers Send Messages to Topics
&lt;/h3&gt;

&lt;p&gt;Producers are applications or systems that generate data and send it to Kafka. Producers write messages (data) to a specific &lt;strong&gt;topic&lt;/strong&gt; in Kafka. A topic acts like a category or a label to organize messages.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: A ride-sharing app might send ride requests to a topic called &lt;code&gt;ride-requests&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Partitioning and Replication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partitioning&lt;/strong&gt;:
Each topic is split into smaller parts called &lt;strong&gt;partitions&lt;/strong&gt;. Messages within a partition are stored in the order they arrive. Kafka assigns each message a unique ID called an &lt;strong&gt;offset&lt;/strong&gt;, which helps keep track of messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Partitioning allows Kafka to handle large amounts of data by distributing it across multiple servers (brokers).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: If the topic &lt;code&gt;ride-requests&lt;/code&gt; has 3 partitions, messages like &lt;code&gt;Request A&lt;/code&gt;, &lt;code&gt;Request B&lt;/code&gt;, and &lt;code&gt;Request C&lt;/code&gt; may go to &lt;code&gt;Partition 1&lt;/code&gt;, &lt;code&gt;Partition 2&lt;/code&gt;, and &lt;code&gt;Partition 3&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Replication&lt;/strong&gt;:
To ensure reliability, Kafka makes copies of partitions across multiple brokers. This means that even if one broker fails, another can serve the data, preventing data loss.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Consumers Read Messages Using Offsets
&lt;/h3&gt;

&lt;p&gt;Consumers are applications that read messages from topics. Each consumer keeps track of the &lt;strong&gt;offset&lt;/strong&gt; of the last message it read. This ensures that consumers process messages in the correct order and don’t miss any data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example: A consumer might read ride requests from the &lt;code&gt;ride-requests&lt;/code&gt; topic and process them to match drivers with passengers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdyqp0j30rb0xqjkqc3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwdyqp0j30rb0xqjkqc3v.png" alt="Message Flow in Kafka" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Applications of Apache Kafka
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is a versatile platform used across industries to handle real-time data at scale. Here are some key applications:&lt;/p&gt;

&lt;h3&gt;
  
  
  Industry Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;E-commerce Platforms:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order Tracking&lt;/strong&gt;: Stream real-time order updates to customers and internal systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory Management&lt;/strong&gt;: Monitor stock levels and synchronize inventory across warehouses instantly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Finance&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fraud Detection&lt;/strong&gt;: Process transactional data in real-time to identify unusual activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trade Monitoring&lt;/strong&gt;: Track and analyze stock trades to meet regulatory requirements and optimize strategies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Social Media Platforms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Activity Streams&lt;/strong&gt;: Stream real-time user activity like likes, comments, and shares for personalized feeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notifications&lt;/strong&gt;: Deliver instant notifications based on user actions or system alerts.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;IoT Applications&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sensor Data Ingestion&lt;/strong&gt;: Collect and process data from IoT devices like temperature sensors or fitness trackers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device Communication&lt;/strong&gt;: Enable real-time communication between connected devices, such as smart home systems.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Apache Kafka&lt;/em&gt; is a distributed platform for real-time data streaming that transforms how businesses handle data. Let’s recap its core aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Definition&lt;/em&gt;: Kafka enables organizations to publish, subscribe to, store, and process streams of records in real-time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Components&lt;/em&gt;: Key elements include topics, partitions, producers, consumers, brokers, and (optionally) Zookeeper.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Workflow&lt;/em&gt;: Producers send data to topics, partitions distribute the load, brokers replicate data for fault tolerance, and consumer groups process data in parallel using offsets for tracking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Benefits&lt;/em&gt;: Kafka provides scalability, fault tolerance, low latency, and support for high-throughput workloads.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/06iRM1Ghr1k"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The next article will discuss how to set up Apache Kafka locally, create topics, partitions, producers and consumers, and send messages across them. Keep reading!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/pragativerma18" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242611%2F3cef560b-1c27-403a-ac74-76260a792597.jpg" alt="pragativerma18"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/pragativerma18/setting-up-apache-kafka-locally-a-step-by-step-guide-2p8" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Setting Up Apache Kafka Locally: A Step-by-Step Guide&lt;/h2&gt;
      &lt;h3&gt;Pragati Verma ・ Jan 21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>computerscience</category>
      <category>webdev</category>
      <category>database</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Scraping Infinite Scroll Pages with a 'Load More' Button: A Step-by-Step Guide</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Mon, 13 Jan 2025 08:29:48 +0000</pubDate>
      <link>https://forem.com/pragativerma18/scraping-infinite-scroll-pages-with-a-load-more-button-a-step-by-step-guide-1ki4</link>
      <guid>https://forem.com/pragativerma18/scraping-infinite-scroll-pages-with-a-load-more-button-a-step-by-step-guide-1ki4</guid>
      <description>&lt;p&gt;Are your scrapers stuck when trying to load data from dynamic web pages? Are you frustrated with infinite scrolls or those pesky "Load more" buttons?&lt;/p&gt;

&lt;p&gt;You're not alone. Many websites today implement these designs to improve user experience—but they can be challenging for web scrapers.&lt;/p&gt;

&lt;p&gt;This tutorial will guide you through a beginner-friendly walkthrough for scraping a &lt;a href="https://www.scrapingcourse.com/button-click" rel="noopener noreferrer"&gt;demo page&lt;/a&gt; with a &lt;strong&gt;Load More&lt;/strong&gt; button. Here’s what the target web page looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sv1xu646wnqtl1pn6xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sv1xu646wnqtl1pn6xe.png" alt="Demo web page for scraping" width="800" height="777"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end, you'll learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Selenium for web scraping.&lt;/li&gt;
&lt;li&gt;Automate the "Load more" button interaction.&lt;/li&gt;
&lt;li&gt;Extract product data such as names, prices, and links.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before diving in, ensure the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python Installed&lt;/strong&gt;: Download and install the latest Python version from &lt;a href="https://python.org" rel="noopener noreferrer"&gt;python.org&lt;/a&gt;, including &lt;a href="https://pypi.org/project/pip/" rel="noopener noreferrer"&gt;pip&lt;/a&gt; during setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic Knowledge&lt;/strong&gt;: Familiarity with web scraping concepts, Python programming, and working with libraries such as requests, BeautifulSoup, and Selenium.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Libraries Required:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requests&lt;/strong&gt;: For sending HTTP requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BeautifulSoup&lt;/strong&gt;: For parsing the HTML content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selenium&lt;/strong&gt;: For simulating user interactions like button clicks in a browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can install these libraries using the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="n"&gt;beautifulsoup4&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before using Selenium, you must install a web driver matching your browser. For this tutorial, we'll use Google Chrome and ChromeDriver. However, you can follow similar steps for other browsers like Firefox or Edge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install the Web Driver&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check your browser version&lt;/strong&gt;:&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Google Chrome and navigate to &lt;strong&gt;Help &amp;gt; About Google Chrome&lt;/strong&gt; from the three-dot menu to find the Chrome version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download ChromeDriver&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visit the &lt;a href="https://developer.chrome.com/docs/chromedriver/downloads" rel="noopener noreferrer"&gt;ChromeDriver download page&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download the driver version that matches your Chrome version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add ChromeDriver to your system PATH:&lt;br&gt;
Extract the downloaded file and place it in a directory like &lt;code&gt;/usr/local/bin&lt;/code&gt; (Mac/Linux) or &lt;code&gt;C:\Windows\System32&lt;/code&gt; (Windows).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Verify Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initialize a Python file &lt;strong&gt;scraper.py&lt;/strong&gt; in your project directory and test that everything is set up correctly by running the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# Ensure ChromeDriver is installed and in PATH
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.scrapingcourse.com/button-click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can execute the above file code by running the following command on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scraper.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the above code runs without errors, it will spin up a browser interface and open the demo page URL as shown below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlxkz1ewdtgnsstfej4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlxkz1ewdtgnsstfej4d.png" alt="Demo Page in Selenium Browser Instance" width="800" height="897"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selenium will then extract the HTML and print the page title. You will see an output like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Load More Button Challenge to Learn Web Scraping - ScrapingCourse.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This verifies that Selenium is ready to use. With all requirements installed and ready to use, you can start accessing the demo page's content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Get Access to the Content
&lt;/h2&gt;

&lt;p&gt;The first step is to fetch the page's initial content, which gives you a baseline snapshot of the page's HTML. This will help you verify connectivity and ensure a valid starting point for the scraping process.&lt;/p&gt;

&lt;p&gt;You will retrieve the HTML content of the page URL by sending a GET request using the Requests library in Python. Here's the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="c1"&gt;# URL of the demo page with products
&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.scrapingcourse.com/button-click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# Send a GET request to the URL
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Check if the request was successful
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;html_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Optional: Preview the HTML
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to retrieve content: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will output the raw HTML containing the data for the first 12 products.&lt;/p&gt;

&lt;p&gt;This quick preview of the HTML ensures that the request was successful and that you're working with valid data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Load More Products
&lt;/h2&gt;

&lt;p&gt;To access the remaining products, you'll need to programmatically click the "Load more" button on the page until no more products are available. Since this interaction involves JavaScript, you will use Selenium to simulate the button click.&lt;/p&gt;

&lt;p&gt;Before writing code, let’s inspect the page to locate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;"Load more"&lt;/strong&gt; button selector (&lt;em&gt;load-more-btn&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;The div holding the product details (&lt;em&gt;product-item&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll get all the products by loading more products, giving you a larger dataset by running the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="c1"&gt;# Set up the WebDriver (make sure you have the appropriate driver installed, e.g., ChromeDriver)
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Open the page
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.scrapingcourse.com/button-click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Loop to click the "Load More" button until there are no more products
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Find the "Load more" button by its ID and click it
&lt;/span&gt;        &lt;span class="n"&gt;load_more_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;load-more-btn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;load_more_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# Wait for the content to load (adjust time as necessary)
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If no "Load More" button is found (end of products), break out of the loop
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No more products to load.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="c1"&gt;# Get the updated page content after all products are loaded
&lt;/span&gt;&lt;span class="n"&gt;html_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;
&lt;span class="c1"&gt;# Close the browser window
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code opens the browser, navigates to the page, and interacts with the "Load more" button. The updated HTML, now containing more product data, is then extracted.&lt;/p&gt;

&lt;p&gt;If you don’t want Selenium to open the browser every time you run this code, it also provides headless browser capabilities. A headless browser has all the functionalities of an actual web browser but no Graphical User Interface (GUI).&lt;/p&gt;

&lt;p&gt;You can enable the headless mode for Chrome in Selenium by defining a &lt;code&gt;ChromeOptions&lt;/code&gt; object and passing it to the &lt;code&gt;WebDriver&lt;/code&gt; Chrome constructor like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="c1"&gt;# instantiate a Chrome options object
&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ChromeOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# set the options to use Chrome in headless mode
&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--headless=new&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# initialize an instance of the Chrome driver (browser) in headless mode
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run the above code, Selenium will launch a headless Chrome instance, so you’ll no longer see a Chrome window. This is ideal for production environments where you don’t want to waste resources on the GUI when running the scraping script on a server.&lt;/p&gt;

&lt;p&gt;Now that the complete HTML content is retrieved extracting specific details about each product is time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Parse Product Information
&lt;/h2&gt;

&lt;p&gt;In this step, you'll use &lt;strong&gt;BeautifulSoup&lt;/strong&gt; to parse the HTML and identify product elements. Then, you'll extract key details for each product, such as the name, price, and links.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="c1"&gt;# Parse the page content with BeautifulSoup
&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Extract product details
&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="c1"&gt;# Find all product items in the grid
&lt;/span&gt;&lt;span class="n"&gt;product_items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;product_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Extract the product name
&lt;/span&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the product price
&lt;/span&gt;    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the product link
&lt;/span&gt;    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the image URL
&lt;/span&gt;    &lt;span class="n"&gt;image_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;img&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create a dictionary with the product details
&lt;/span&gt;    &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image_url&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# Print the extracted product details
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Link: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Image URL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output, you should see a structured list of product details, including the name, image URL, price, and product page link, like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Name: Chaz Kangeroo Hoodie
Price: &lt;span class="nv"&gt;$52&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/chaz-kangeroo-hoodie
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh01-gray_main.jpg
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
Name: Teton Pullover Hoodie
Price: &lt;span class="nv"&gt;$70&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/teton-pullover-hoodie
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh02-black_main.jpg
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will organize the raw HTML data into a structured format, making it easier to work with and preparing the output data for further processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Export Product Information to CSV
&lt;/h2&gt;

&lt;p&gt;You can now organize the extracted data into a CSV file, which makes it easier to analyze or share. Python's CSV module helps with this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="c1"&gt;# Write the product information to a CSV file
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;products.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will create a new CSV file with all the required product details.&lt;/p&gt;

&lt;p&gt;Here's the complete code for an overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import time
import csv
# Set up the WebDriver (make sure you have the appropriate driver installed, e.g., ChromeDriver)
driver = webdriver.Chrome()
# Open the page
driver.get("https://www.scrapingcourse.com/button-click")
# Loop to click the "Load More" button until there are no more products to load
while True:
    try:
        # Find the "Load more" button by its ID and click it
        load_more_button = driver.find_element(By.ID, "load-more-btn")
        load_more_button.click()
        # Wait for the content to load (adjust time as necessary)
        time.sleep(2)
    except Exception as e:
        # If no "Load More" button is found (end of products), break out of the loop
        print("No more products to load.")
        break
# Get the updated page content after all products are loaded
html_content = driver.page_source
# Close the browser window
driver.quit()
# Parse the page content with BeautifulSoup
soup = BeautifulSoup(html_content, 'html.parser')
# Extract product details
products = []
# Find all product items in the grid
product_items = soup.find_all('div', class_='product-item')
for product in product_items:
    # Extract the product name
    name = product.find('span', class_='product-name').get_text(strip=True)

    # Extract the product price
    price = product.find('span', class_='product-price').get_text(strip=True)

    # Extract the product link
    link = product.find('a')['href']

    # Extract the image URL
    image_url = product.find('img')['src']

    # Create a dictionary with the product details
    products.append({
        'name': name,
        'price': price,
        'link': link,
        'image_url': image_url
    })
# Print the extracted product details
for product in products[:2]: # You can modify the slice as needed to check more products
    print(f"Name: {product['name']}")
    print(f"Price: {product['price']}")
    print(f"Link: {product['link']}")
    print(f"Image URL: {product['image_url']}")
    print('-' * 30)
# Write the product information to a CSV file
with open("products.csv", mode="w", newline="") as file:
    writer = csv.DictWriter(file, fieldnames=["name", "image_url", "price", "link"])
    writer.writeheader()
    for product in products:
        writer.writerow(product)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will create a &lt;code&gt;products.csv&lt;/code&gt; which would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;name,image_url,price,link
Chaz Kangeroo Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh01-gray_main.jpg,&lt;span class="nv"&gt;$52&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/chaz-kangeroo-hoodie
Teton Pullover Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh02-black_main.jpg,&lt;span class="nv"&gt;$70&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/teton-pullover-hoodie
Bruno Compete Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh03-black_main.jpg,&lt;span class="nv"&gt;$63&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/bruno-compete-hoodie
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Get Extra Data for Top Products
&lt;/h2&gt;

&lt;p&gt;Now, let's say you want to identify the top 5 highest-priced products and extract additional data (such as the product description and SKU code) from their individual pages. You can do that using the code as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sort products by price in descending order
&lt;/span&gt;&lt;span class="n"&gt;sorted_products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Scrape extra details for the top 5 products
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sorted_products&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;sku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sku&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No SKU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the complete code for an overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="c1"&gt;# Set up the WebDriver (make sure you have the appropriate driver installed, e.g., ChromeDriver)
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Open the page
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.scrapingcourse.com/button-click&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Loop to click the "Load More" button until there are no more products to load
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Find the "Load more" button by its ID and click it
&lt;/span&gt;        &lt;span class="n"&gt;load_more_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;load-more-btn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;load_more_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="c1"&gt;# Wait for the content to load (adjust time as necessary)
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If no "Load More" button is found (end of products), break out of the loop
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No more products to load.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="c1"&gt;# Get the updated page content after all products are loaded
&lt;/span&gt;&lt;span class="n"&gt;html_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;

&lt;span class="c1"&gt;# Parse the page content with BeautifulSoup
&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Extract product details
&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="c1"&gt;# Find all product items in the grid
&lt;/span&gt;&lt;span class="n"&gt;product_items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;product_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Extract the product name
&lt;/span&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the product price
&lt;/span&gt;    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Convert price to a float for sorting (remove '$' or other symbols as needed)
&lt;/span&gt;    &lt;span class="n"&gt;price_float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the product link
&lt;/span&gt;    &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract the image URL
&lt;/span&gt;    &lt;span class="n"&gt;image_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;img&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Create a dictionary with the product details
&lt;/span&gt;    &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price_float&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;price_float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# store as float for sorting
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image_url&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# Sort products by price (descending order)
&lt;/span&gt;&lt;span class="n"&gt;sorted_products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price_float&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Get the top 5 highest-priced products
&lt;/span&gt;&lt;span class="n"&gt;top_5_products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sorted_products&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# Visit each of the top 5 product pages and extract extra data
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top_5_products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Open the product page
&lt;/span&gt;    &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Wait for the page to load
&lt;/span&gt;    &lt;span class="c1"&gt;# Parse the page content of the product page
&lt;/span&gt;    &lt;span class="n"&gt;product_page_soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Extract product description and SKU
&lt;/span&gt;    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product_page_soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product-description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No description available&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;sku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product_page_soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;span&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sku_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sku&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No SKU available&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="c1"&gt;# Add the extra data to the product details
&lt;/span&gt;    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;description_text&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sku_code&lt;/span&gt;
&lt;span class="c1"&gt;# Close the browser window after scraping product pages
&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Print the extracted product details for the top 5 products
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;top_5_products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Link: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Image URL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKU: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Write the product information to a CSV file, including the extra data
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;products.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fieldnames&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeheader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;link&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code sorts the products by price in descending order. Then, for the top 5 highest-priced products, the script opens their product pages and extracts the product description and SKU using BeautifulSoup.&lt;/p&gt;

&lt;p&gt;The output of the above code will be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Name: Lando Gym Jacket
Price: &lt;span class="nv"&gt;$99&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/lando-gym-jacket
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mj08-gray_main.jpg
Description: No description available
SKU: MJ08
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
Name: Ingrid Running Jacket
Price: &lt;span class="nv"&gt;$84&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/ingrid-running-jacket
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/wj04-white_main.jpg
Description: No description available
SKU: WJ04
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
Name: Zeppelin Yoga Pant
Price: &lt;span class="nv"&gt;$82&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/zeppelin-yoga-pant
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mp08-green_main.jpg
Description: No description available
SKU: MP08
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
Name: Zeppelin Yoga Pant
Price: &lt;span class="nv"&gt;$82&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/zeppelin-yoga-pant
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mp08-green_main.jpg
Description: No description available
SKU: MP08
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
Name: Juno Jacket
Price: &lt;span class="nv"&gt;$77&lt;/span&gt;
Link: https://scrapingcourse.com/ecommerce/product/juno-jacket
Image URL: https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/wj06-purple_main.jpg
Description: No description available
SKU: No SKU available
&lt;span class="nt"&gt;------------------------------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code will update the &lt;code&gt;products.csv&lt;/code&gt; and it will now have information like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;name,image_url,price,link,description,sku
Chaz Kangeroo Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh01-gray_main.jpg,&lt;span class="nv"&gt;$52&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/chaz-kangeroo-hoodie,,
Teton Pullover Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh02-black_main.jpg,&lt;span class="nv"&gt;$70&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/teton-pullover-hoodie,,
Bruno Compete Hoodie,https://scrapingcourse.com/ecommerce/wp-content/uploads/2024/03/mh03-black_main.jpg,&lt;span class="nv"&gt;$63&lt;/span&gt;,https://scrapingcourse.com/ecommerce/product/bruno-compete-hoodie,,
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Scraping pages with infinite scrolling or "Load more" buttons can seem challenging, but using tools like Requests, Selenium, and BeautifulSoup simplifies the process.&lt;/p&gt;

&lt;p&gt;This tutorial showed how to retrieve and process product data from a demo page, saving it in a structured format for quick and easy access.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;See all the code snippets &lt;a href="https://gist.github.com/PragatiVerma18/e1f3b48204a816ef55269311c9dbbc53" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding JavaScript Deobfuscation in Web Scraping</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Tue, 17 Dec 2024 07:30:33 +0000</pubDate>
      <link>https://forem.com/pragativerma18/understanding-javascript-deobfuscation-in-web-scraping-5c2f</link>
      <guid>https://forem.com/pragativerma18/understanding-javascript-deobfuscation-in-web-scraping-5c2f</guid>
      <description>&lt;p&gt;Web scraping often involves extracting data from websites, but it can be challenging in many cases. The data you need might not be directly accessible due to obfuscation techniques used by websites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript obfuscation&lt;/strong&gt;, in particular, is a method used to make the scraping process more difficult using Javascript. &lt;/p&gt;

&lt;p&gt;In this article, we’ll discuss JavaScript deobfuscation, why it matters in web scraping, and how to handle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JavaScript Obfuscation in Web Scraping?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JavaScript obfuscation&lt;/strong&gt; is a technique for making code harder to interpret by humans or automated tools. Websites often obfuscate JavaScript to protect their data or hinder web scraping attempts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common obfuscation techniques can involve:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changing Variable and Function Names&lt;/strong&gt;: Variable and function names are renamed to random strings such as &lt;code&gt;a1&lt;/code&gt;, &lt;code&gt;b2&lt;/code&gt; and so on, making it hard to understand their purpose.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encoding Data&lt;/strong&gt;: Strings, URLs or sensitive data are encrypted or encoded using &lt;code&gt;base64&lt;/code&gt; or other encoding methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Flow Obfuscation&lt;/strong&gt;: The order of code execution can be altered to make it harder to follow the logic and flow of the program.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dead Code Insertion&lt;/strong&gt;: Irrelevant or unreachable code is added to increase the complexity and size of the script.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minification&lt;/strong&gt;: Unnecessary whitespace and comments are removed to reduce readability and shrink the code size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function Wrapping and Indirection&lt;/strong&gt;: Important functions are wrapped in multiple layers or executed through indirect calls to add complexity and hide their true purpose.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simple example of JavaScript obfuscation:&lt;/p&gt;

&lt;h3&gt;
  
  
  Original JS Code:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;productPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;productName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wireless Mouse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;displayProductInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product Name: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;productName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Price: $&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;productPrice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;displayProductInfo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Obfuscated JS Code:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;_0x1a2b3c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x57&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x69&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x72&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x65&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x6C&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x65&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x73&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x73&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x20&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x4D&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x6F&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x75&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x73&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x65&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x4C&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x65&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x74&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x20&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x70&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x72&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x6F&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x64&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x75&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x63&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x74&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x50&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x72&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x69&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x63&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x65&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;x24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_0x4c3b1a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_0x6d24f5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wireless Mouse&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_0x44a5bc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_0x1a2b3c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]](&lt;/span&gt;&lt;span class="nx"&gt;_0x1a2b3c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;_0x6d24f5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_0x1a2b3c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]](&lt;/span&gt;&lt;span class="nx"&gt;_0x1a2b3c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;_0x4c3b1a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;_0x44a5bc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JavaScript code may also alter requests, load additional data, or manage how the &lt;em&gt;DOM (Document Object Model)&lt;/em&gt; is populated, making it harder to trace. &lt;/p&gt;

&lt;p&gt;This is where Javascript deobfuscation comes in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is JavaScript Deobfuscation Important?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Deobfuscation&lt;/em&gt; is essential because many websites rely on obfuscation techniques to prevent scraping. To bypass these defenses, web scrapers must reverse the obfuscation process. Without deobfuscation, scrapers might miss crucial information or struggle to interact with dynamic elements properly.&lt;/p&gt;

&lt;p&gt;In the context of scraping, understanding JavaScript deobfuscation allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extract hidden or dynamically loaded data&lt;/strong&gt;: Deobfuscation helps reveal data stored in JavaScript variables, encoded strings, or dynamically generated HTML, such as product prices, stock levels, or user reviews.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interact with obfuscated JavaScript code&lt;/strong&gt;: By reversing obfuscation techniques, you can better understand and interact with complex JavaScript code to access content that is otherwise hidden or manipulated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bypass anti-scraping measures&lt;/strong&gt;: Deobfuscation helps overcome JavaScript-based anti-scraping mechanisms like CAPTCHAs, rate limiting, or browser fingerprinting, allowing scrapers to mimic human behaviour and bypass these defenses.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Does JavaScript Deobfuscation Work?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Javascript deobfuscation&lt;/em&gt;&lt;/strong&gt; refers to the process of interpreting or reversing obfuscated JavaScript code to reveal its original functionality.&lt;/p&gt;

&lt;p&gt;Here are some of the common approaches for deobfuscating JavaScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Inspection&lt;/strong&gt;: Reviewing JavaScript code to identify patterns and decode obfuscated elements can be effective but is often time-intensive and demands a strong understanding of JavaScript.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Deobfuscators&lt;/strong&gt;: Tools like &lt;a href="https://github.com/svent/jsdetox" rel="noopener noreferrer"&gt;JSDetox&lt;/a&gt; or &lt;a href="https://lelinhtinh.github.io/de4js/" rel="noopener noreferrer"&gt;de4js&lt;/a&gt; can help you automate the process by detecting the common obfuscation patterns and helping you reverse them into more readable code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging Tools&lt;/strong&gt;: Web scraping developers can use browser developer tools to step through JavaScript code and observe its execution. This helps trace how the script manipulates the page or communicates with the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Beautifiers&lt;/strong&gt;: These tools format obfuscated code to make it more readable, which is often the first step before more complex deobfuscation techniques are applied.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solutions for Dealing with Obfuscated JavaScript
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Headless Browsers&lt;/strong&gt;: Tools like &lt;a href="https://pptr.dev/" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt; or &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; help deal with JavaScript-heavy websites. These headless browsers can execute JavaScript and allow scrapers to interact with the page as if they’re a real user, helping to bypass complex obfuscation techniques.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloudflare Workarounds&lt;/strong&gt;: Some websites use &lt;a href="https://www.cloudflare.com/en-in/" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt; to protect against scraping. Scrapers can bypass Cloudflare's anti-bot protection by rotating user-agent headers or solving JavaScript challenges. The most common is the &lt;a href="https://developers.cloudflare.com/waf/reference/cloudflare-challenges/" rel="noopener noreferrer"&gt;Cloudflare JS Challenge&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Data Scraping&lt;/strong&gt;: Many scraping tools are designed to replicate user behaviour on JavaScript-heavy websites, allowing them to interact with elements like buttons or drop-downs to load dynamic content.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;JavaScript deobfuscation is crucial in web scraping, enabling you to bypass obfuscation techniques and access the data needed. While manual deobfuscation can be time-consuming, automated tools and headless browsers make the process more efficient.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>The Complete Guide to Logging in Django</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Thu, 18 Apr 2024 13:51:44 +0000</pubDate>
      <link>https://forem.com/pragativerma18/the-complete-guide-to-logging-in-django-5fde</link>
      <guid>https://forem.com/pragativerma18/the-complete-guide-to-logging-in-django-5fde</guid>
      <description>&lt;p&gt;Applications running in production can’t tell you directly what’s going on under the hood, so you need a way to keep track of their behavior. Knowing what’s going on in your code at any given time benefits you from both a technical and a business standpoint. With this information, engineers and product managers can make better decisions about which systems to repair or how to improve user experience (UX). &lt;/p&gt;

&lt;p&gt;The most straightforward way to achieve this is with logging. You can code the program during development to share relevant information while running that could be useful in analysis, debugging, and further troubleshooting.  &lt;/p&gt;

&lt;p&gt;Django is a popular Python web application framework, used by small and large organizations. Python offers a powerful built-in &lt;a href="https://docs.python.org/3/library/logging.html" rel="noopener noreferrer"&gt;logging module&lt;/a&gt; to log events from applications and libraries. The library is flexible and can be easily customized to fit any application. You can implement it this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Start reading database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# read database here
&lt;/span&gt;&lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;john&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tom&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Records: %s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Updating records ...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# update records here
&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Finish updating records&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the program is run, you can see the records on the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO:__main__:Start reading database
INFO:__main__:Updating records ...
INFO:__main__:Finish updating records
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This article will delve deeper into the logging concepts that every developer should know. You’ll learn how to log significant data, how to route the logs, and how to consolidate them for insights into your Django applications. You’ll also learn best practices to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Logs?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Logs&lt;/em&gt; are the records of events that occur while running software. They contain information about the application, system performance, or user activities. &lt;em&gt;Loggers&lt;/em&gt; are the objects that a developer interacts with to print out the information. They help you tell the program what to log and how to do it. &lt;/p&gt;

&lt;p&gt;Adding logging to your code involves three critical steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choosing what data to output and where in the code to do so&lt;/li&gt;
&lt;li&gt;Choosing how to format the logs&lt;/li&gt;
&lt;li&gt;Choosing where to transmit the logs (e.g., stdout or syslog) &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Implement Logging
&lt;/h2&gt;

&lt;p&gt;To implement logging in a Django application, you must consider the following factors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging Levels
&lt;/h3&gt;

&lt;p&gt;The Python logging library adds several types of metadata to provide valuable context around the log messages. This can help in diagnosing a problem or analyzing what’s happening inside the code while the application is running. For example, log levels define the severity level of log events, which can be used to segment logs so you get the most relevant log message at any specified time. &lt;/p&gt;

&lt;p&gt;You can use log levels to help prioritize log messages. For instance, when you’re developing an application, &lt;code&gt;DEBUG&lt;/code&gt; information is most relevant; while you’re running the application, you can leave &lt;code&gt;INFO&lt;/code&gt; logs to indicate certain events.&lt;/p&gt;

&lt;p&gt;The Python logging package comes with five logging levels: &lt;code&gt;critical&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;warning&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;, and &lt;code&gt;debug&lt;/code&gt;. These levels are denoted by constants with the same name: &lt;code&gt;logging.CRITICAL&lt;/code&gt;, &lt;code&gt;logging.ERROR&lt;/code&gt;, &lt;code&gt;logging.WARNING&lt;/code&gt;, &lt;code&gt;logging.INFO&lt;/code&gt;, and &lt;code&gt;logging.DEBUG&lt;/code&gt;, with values of 50, 40, 30, 20, and 10. A level’s meaning is determined at runtime by its value. &lt;/p&gt;

&lt;p&gt;The community-wide applicability rules for logging levels are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DEBUG&lt;/strong&gt;: &lt;code&gt;logging.DEBUG&lt;/code&gt; can be used to log detailed information for debugging code in development, such as when the app starts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;INFO&lt;/strong&gt;: &lt;code&gt;logging.INFO&lt;/code&gt; can be used to log information about the code if it is running as expected, such as when a process starts in the app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: &lt;code&gt;logging.WARNING&lt;/code&gt; can be used to report unexpected behavior that could cause a future problem but isn’t impacting the current process of the application, such as when the app detects low memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ERROR&lt;/strong&gt;: &lt;code&gt;logging.ERROR&lt;/code&gt; can be used to report events when the software fails to perform some action, such as when the app fails to save data due to insufficient permissions given to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CRITICAL&lt;/strong&gt;: &lt;code&gt;logging.CRITICAL&lt;/code&gt; can be used to report serious errors that impact the continued execution of the application, such as when the application fails to store data due to insufficient memory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;logging.Logger&lt;/code&gt; object offers the primary interface to Python’s logging library. These objects include methods for issuing log requests and for querying and modifying their state, as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Logger.critical(msg, *args, **kwargs)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Logger.error(msg, *args, **kwargs)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Logger.debug(msg, *args, **kwargs)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Logger.info(msg, *args, **kwargs)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Logger.warn(msg, *args, **kwargs)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, loggers provide the following two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Logger.log(level, msg, *args, **kwargs)&lt;/code&gt; sends log requests with defined logging levels. When you’re using custom logging levels, this approach comes in handy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Logger.exception(msg, *args, **kwargs)&lt;/code&gt; sends log requests with the logging level &lt;code&gt;ERROR&lt;/code&gt; and includes the current exception in the log entries. This function should be called from an exception handler.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logging Handlers
&lt;/h3&gt;

&lt;p&gt;Logging handlers are used to determine where to put the logs—system logs or files. Unless explicitly specified, the logging library uses a &lt;code&gt;StreamHandler&lt;/code&gt; for sending the log messages to the console or &lt;code&gt;sys.stderr&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Handlers also format log records into log entries using their formatters. The formatter for a handler can be set by clients using the &lt;code&gt;Handler.setFormatter(formatter)&lt;/code&gt; function. If a handler doesn’t have a formatter, the library’s default formatter is used. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;logging.handler&lt;/code&gt; module includes &lt;a href="https://docs.python.org/3/howto/logging.html#useful-handlers" rel="noopener noreferrer"&gt;fifteen useful handlers&lt;/a&gt; that span a range of use cases (including the ones mentioned above). The most commonly used logging handlers are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;StreamHandler&lt;/code&gt;&lt;/strong&gt; transmits logs to a stream-like object, such as a console, using &lt;code&gt;stdout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;FileHandler&lt;/code&gt;&lt;/strong&gt; redirects log events to a file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;SyslogHandler&lt;/code&gt;&lt;/strong&gt; routes logs to your system’s syslog daemon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;HTTPHandler&lt;/code&gt;&lt;/strong&gt; allows you to deliver logs through HTTP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;NullHandler&lt;/code&gt;&lt;/strong&gt; redirects your logs to nowhere, which is helpful for temporarily halting logging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Logging Formatters
&lt;/h3&gt;

&lt;p&gt;Log messages from the logging library follow this default format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;LEVEL&amp;gt;:&amp;lt;LOGGER_NAME&amp;gt;:&amp;lt;MESSAGE&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, they can be customized to add more information using &lt;code&gt;logging.Formatter&lt;/code&gt; objects to change them into a string-based log entry. &lt;/p&gt;

&lt;p&gt;Django leverages the potential of logging by using the Python &lt;code&gt;logging&lt;/code&gt; module by default, which provides different ways to create customized loggers through handlers, formats, and levels. The logging module is capable of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multithreading execution&lt;/li&gt;
&lt;li&gt;Categorizing messages via different log levels&lt;/li&gt;
&lt;li&gt;Setting the destination of the logs&lt;/li&gt;
&lt;li&gt;Controlling what to include and what to emit&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Add Logging in Django
&lt;/h2&gt;

&lt;p&gt;To use logging in your Django project, follow these steps.&lt;/p&gt;

&lt;p&gt;Configure the &lt;code&gt;settings.py&lt;/code&gt; for various loggers, handlers, and filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging.config&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils.log&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_LOGGING&lt;/span&gt;

&lt;span class="c1"&gt;# Disable Django's logging setup
&lt;/span&gt;&lt;span class="n"&gt;LOGGING_CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="n"&gt;LOGLEVEL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;LOGLEVEL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;info&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dictConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;disable_existing_loggers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;formatters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;# exact format is not important, this is the minimum information
&lt;/span&gt;            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s %(name)-12s %(levelname)-8s %(message)s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_LOGGING&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;formatters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;handlers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# console logs to stderr
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;console&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;class&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;logging.StreamHandler&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;formatter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_LOGGING&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;handlers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;loggers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# default for all undefined Python modules
&lt;/span&gt;        &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WARNING&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;handlers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;console&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;# Our application code
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LOGLEVEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;handlers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;console&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="c1"&gt;# Avoid double logging because of root logger
&lt;/span&gt;            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;propagate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;# Default runserver request logging
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_LOGGING&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;loggers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.server&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the server. You’ll be able to see logs on your console or log files, depending on the configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Logging in Django
&lt;/h2&gt;

&lt;p&gt;Logging is vital to your Django application because it can save you time in crucial situations. Follow these best practices for implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create loggers using the &lt;code&gt;logging.getLogger()&lt;/code&gt; factory function, so that the logging library can manage the mapping of names to instances and maintain a hierarchy of logs. This way, you can use the logger’s name to access it in different parts of the application, and only a set number of loggers will be created at runtime. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify proper log levels to lower the risks of deployment and ensure effective debugging. This helps prevent the flooding of log files with trivial information due to inappropriate settings. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Format logs correctly so that the system can parse them. This is useful when manually reading the logs isn’t enough, such as for audits or alerts. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don’t log sensitive information like passwords, authorization tokens, personally identifiable information (PII), credit card numbers, or session identifiers that the user has chosen. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use fault-tolerant protocols while transferring logs to avoid packet loss. Secure log data by encrypting it and removing any sensitive information before transferring it. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create meaningful log messages so that you can easily tell what happened from the log file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance log messages by including additional information. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don’t make log messages reliant on the content of prior messages, since the previous messages may not display if they’re logged at different levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that logs are written asynchronously during log generation. Buffer or queue logs to prevent the program from stalling. Organize logs so that it’s simple to make changes as needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a wrapper to shield the program from third-party tools. Use standard date and time formats, add timestamps, use log levels appropriately, and include a stack trace when reporting the error to make logs more human-readable. Include the thread’s name in a multithreaded program.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use filters or &lt;code&gt;logging.LoggerAdapter&lt;/code&gt; to inject local contextual information, or use &lt;code&gt;logging.setLogRecordFactory()&lt;/code&gt; to inject global contextual information in the log records. Don’t log too much, though, or it might become difficult to extract value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you use &lt;code&gt;FileHandler&lt;/code&gt; to write logs, the log file will expand over time and eventually take up all your storage space. In the production environment, utilize &lt;code&gt;RotatingFileHandler&lt;/code&gt; instead of &lt;code&gt;FileHandler&lt;/code&gt; to prevent this problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you have many different servers and log files, set up a central log system for all critical messages so you can quickly monitor it for problems.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logging configuration in Django is simple, but it can get complicated when dealing with large applications. Aside from the Python logging module, you can also use popular logging tools such as &lt;a href="https://newrelic.com/platform/log-management" rel="noopener noreferrer"&gt;NewRelic&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Logging can help you improve your application development and end-user experience. Because Django is a Python-based framework, Python’s logging system benefits you in several ways, and you can implement it fairly easily. Remember to follow the above best practices to simplify your setup and ensure better-quality results. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>django</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Handle N+1 Queries for Optimal Database Performance in Django?</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Mon, 01 Apr 2024 14:34:33 +0000</pubDate>
      <link>https://forem.com/pragativerma18/how-to-handle-n1-queries-for-optimal-database-performance-in-django-37ko</link>
      <guid>https://forem.com/pragativerma18/how-to-handle-n1-queries-for-optimal-database-performance-in-django-37ko</guid>
      <description>&lt;p&gt;As a backend developer, prioritizing efficiency is the foremost metric for your application's success. Every database query has implications for its performance, scalability, and overall responsiveness, and one of the most common issues developers face is the &lt;strong&gt;N+1 query&lt;/strong&gt; problem.&lt;/p&gt;

&lt;p&gt;N+1 queries can lead to sluggish user experience, decreased system throughput, and even scalability challenges as the volume of the data and user interactions increase over time, thus, addressing N+1 queries is very important for ensuring optimal database performance and responsiveness.&lt;/p&gt;

&lt;p&gt;In this article, we'll learn what N+1 queries are, how to find them, and finally, how to resolve them in Django. So, let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are N+1 Queries?
&lt;/h2&gt;

&lt;p&gt;N+1 query refers to a common scenario in database management where an initial query to retrieve data is followed by N additional queries to fetch related data for each result of the initial query, resulting in a cascade of queries that leads to potentially significant performance overhead.&lt;/p&gt;

&lt;p&gt;Imagine you're at a grocery store and you need to buy ingredients for a recipe. The N+1 problem is like going to the store multiple times, once for each ingredient, instead of making a single trip and getting everything you need at once. It's inefficient and takes more time and effort than necessary. Similarly, in programming, N+1 queries involve making multiple database queries for related data instead of optimizing and fetching everything in one go, leading to slower performance and wasted resources.&lt;/p&gt;

&lt;p&gt;This problem usually arises when using an ORM(Object-Relational Mapping) in web frameworks such as Django or Ruby on Rails, and can impact the performance and scalability of the applications.&lt;/p&gt;

&lt;p&gt;The most common occurrence of N+1 queries is when nested loops are used to iterate over the query results and fetch the related data within the inner loops. As you can imagine, this can lead to multiple queries being executed for each iteration of the outer loop.&lt;/p&gt;

&lt;p&gt;Let's see an example. Suppose we have two models: Category and Product, where each product belongs to a category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DecimalField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_digits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decimal_places&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's say we want to retrieve all products along with their categories' names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_product_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Initial query to fetch all products
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Each access to category.name triggers an additional query
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code example, we retrieve all products and then iterate over each product to print its name and the name of its category.&lt;/p&gt;

&lt;p&gt;However, accessing &lt;code&gt;product.category.name&lt;/code&gt; for each product triggers an additional query to fetch the category's name, leading to the N+1 query problem.&lt;/p&gt;

&lt;p&gt;Now, that we understand what N+1 queries are, let's see how to find them easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to find N+1 Queries in Django?
&lt;/h2&gt;

&lt;p&gt;If you're unaware of what to search for, the N+1 problem might slip under the radar during development and testing. It might only become evident in production when dealing with a larger database.&lt;/p&gt;

&lt;p&gt;However, once identified, fixing N+1 queries is straightforward and can lead to significant performance enhancements for your application.&lt;/p&gt;

&lt;p&gt;There are several ways to detect N+1 queries in your Django application -&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using APM tools like &lt;a href="https://newrelic.com/" rel="noopener noreferrer"&gt;NewRelic&lt;/a&gt;, &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;, &lt;a href="https://www.datadoghq.com/" rel="noopener noreferrer"&gt;Datadog&lt;/a&gt;, etc to monitor the performance of your application and while you're on it, they can help you identify N+1 queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;a href="https://django-debug-toolbar.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;Django Debug Toolbar&lt;/a&gt;, a third-party debugging tool that provides detailed information about each HTTP request, including executed queries. Install and configure the debug toolbar in your Django project, and then inspect the SQL queries generated for each request. Look for patterns where multiple similar queries are executed, indicating potential N+1 query issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable SQL query logging in your Django settings. Set the &lt;code&gt;django.db.backends&lt;/code&gt; logger to the &lt;code&gt;DEBUG&lt;/code&gt; level to log all executed SQL queries. Inspect the logged queries, and look for patterns where multiple similar queries are executed in succession, indicating potential N+1 query issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, that we know how to find N+1 queries, the next step is to learn how to fix them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Fix N+1 Queries Once They're Identified?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are the ways to resolve N+1 queries in your Django codebase -&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Use &lt;code&gt;select_related()&lt;/code&gt; and &lt;code&gt;prefetch_related()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;An easy way to optimize queries and prevent N+1 queries is by employing joins. Joins enable the consolidation of related records into a single query, eliminating the need to query the database for each record separately. Using the joins method, you can specify the associations to be merged.&lt;/p&gt;

&lt;p&gt;In Django, wherever applicable, you can use Django's QuerySet methods &lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#select-related" rel="noopener noreferrer"&gt;&lt;code&gt;select_related()&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#prefetch-related" rel="noopener noreferrer"&gt;&lt;code&gt;prefetch_related()&lt;/code&gt;&lt;/a&gt; to optimize data retrieval.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;select_related()&lt;/code&gt;: Use when fetching related objects via foreign key relationships. It performs an SQL join operation to fetch related objects in a single query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, to fix the N+1 query when fetching the product list, we can &lt;code&gt;select_related&lt;/code&gt; like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_product_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Fixed
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;prefetch_related()&lt;/code&gt;: Use when fetching related objects via many-to-many or reverse foreign key relationships. It fetches related objects in separate queries and caches them for efficient retrieval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, suppose we have a view that fetches all categories along with their related products:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# N+1 query issue
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we again have a scenario where N+1 queries would occur. To fix this, we can use &lt;code&gt;prefetch_related&lt;/code&gt; to fetch the related &lt;code&gt;Product&lt;/code&gt; objects in separate queries and cache them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetch_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Fixed
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Use &lt;code&gt;annotate()&lt;/code&gt; to perform calculations
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#annotate" rel="noopener noreferrer"&gt;&lt;code&gt;annotate()&lt;/code&gt;&lt;/a&gt; can be used to perform calculations across related models without requiring additional database queries for each related object.&lt;/p&gt;

&lt;p&gt;It can help in solving N+1 queries by allowing you to aggregate or annotate related data into the initial queryset, thus reducing the need for subsequent queries to fetch related information.&lt;/p&gt;

&lt;p&gt;Suppose we want to retrieve all categories along with the count of products in each category.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;annotate()&lt;/code&gt;, if we retrieve all categories and then iterate over each category to count the number of products it contains, it would result in N+1 queries, where N is the number of categories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;product_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# N+1 queries issue
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product Count:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To solve the N+1 queries issue using &lt;code&gt;annotate()&lt;/code&gt;, we can annotate the queryset with the count of products for each category:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;product&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product Count:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Fixed, no additional queries
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Use &lt;code&gt;Subquery&lt;/code&gt; for complex calculations
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/expressions/#subquery-expressions" rel="noopener noreferrer"&gt;Subqueries&lt;/a&gt; can help in solving N+1 queries by allowing you to perform a separate query to fetch related data for each record in the initial queryset, without resorting to multiple queries in a loop. This can be particularly useful when the related data needs to be aggregated or filtered based on each record in the initial queryset.&lt;/p&gt;

&lt;p&gt;Let's use the &lt;code&gt;Product&lt;/code&gt; and &lt;code&gt;Category&lt;/code&gt; models again to demonstrate how subqueries can help in solving N+1 queries.&lt;/p&gt;

&lt;p&gt;Suppose we want to retrieve all categories along with the total price of all products in each category.&lt;/p&gt;

&lt;p&gt;Without using subqueries, if we retrieve all categories and then iterate over each category to calculate the total price of products, it would result in N+1 queries, where N is the number of categories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;total_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# N+1 queries issue
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total Price:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;total_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To solve the N+1 queries issue using subqueries, we can use a subquery to annotate the queryset with the total price of products for each category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Subquery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;category_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;total_price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Subquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;OuterRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;output_field&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DecimalField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Category:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total Price:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Fixed, no additional queries
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, we use a subquery to fetch the total price of products for each category. The &lt;code&gt;Subquery()&lt;/code&gt; function performs a separate query for each category in the initial queryset, fetching the total price of products filtered by the category's primary key.&lt;/p&gt;

&lt;p&gt;This allows us to annotate the Category queryset with the total price of products for each category in a single query, effectively solving the N+1 queries issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;N+1 queries can really slow down your Django app. But don't worry! You can fix this issue by using simple tricks like select_related, prefetch_related, and subqueries. These techniques help you fetch related stuff efficiently, avoiding the N+1 query problem.&lt;/p&gt;

&lt;p&gt;The interesting thing to understand at this point is that the most difficult part of the process is to find the N+1 queries while fixing them is quite simple.&lt;/p&gt;

&lt;p&gt;Just keep an eye on your database queries and use the right methods to make your Django app run faster.&lt;/p&gt;

&lt;p&gt;I hope you found this article useful. Do follow me for more insightful tech articles. In case you want to connect with me, follow the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/pragativerma18/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://github.com/PragatiVerma18/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/pragati_verma18" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>django</category>
      <category>python</category>
      <category>database</category>
    </item>
    <item>
      <title>Git Reflog: Rescuing Lost Work in Git's Timeline</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Sat, 30 Mar 2024 14:34:25 +0000</pubDate>
      <link>https://forem.com/pragativerma18/git-reflog-rescuing-lost-work-in-gits-timeline-108c</link>
      <guid>https://forem.com/pragativerma18/git-reflog-rescuing-lost-work-in-gits-timeline-108c</guid>
      <description>&lt;p&gt;Have you ever found yourself in a panic when you accidentally delete a commit or lose track of changes in your Git repository? Don't worry, you're not alone. Git, being the most powerful version control system, has a safety net called "Git Reflog" that can save the day.&lt;/p&gt;

&lt;p&gt;In this article, we'll take a beginner-friendly dive into the world of &lt;strong&gt;Git Reflog&lt;/strong&gt; and learn how it works, why it's essential, and how it can rescue your lost work in no time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Git Reflog?
&lt;/h2&gt;

&lt;p&gt;Git has a feature called "reference log," or simply "reflog," that maintains a chronological record of reference updates in a repository. These references include changes to branches, commits, and other pointers, such as the HEAD pointer which indicates the currently checked-out branch or commit. Each entry in the reflog represents a snapshot of the repository's state at a particular point in time, along with information about the action that caused the change.&lt;/p&gt;

&lt;p&gt;Each log entry in a reflog file typically contains the following information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Commit Hash:&lt;/strong&gt; The hash of the commit being referenced or affected by the operation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Previous Commit Hash:&lt;/strong&gt; The hash of the commit before the operation was performed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Action:&lt;/strong&gt; The action that triggered the reference update (e.g., commit, checkout, reset).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Date and Time:&lt;/strong&gt; The timestamp of when the operation occurred.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; The name and email address of the user who operated.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, reflogs retain a record of each HEAD position for the past 90 days.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's important to note that reflog history is confined to the local repository and isn't accessible remotely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These reflogs are stored in specific directories within the local repository's &lt;code&gt;.git&lt;/code&gt; directory. These directories can be located at &lt;code&gt;.git/logs/refs/heads/&lt;/code&gt;, &lt;code&gt;.git/logs/HEAD&lt;/code&gt;, and also &lt;code&gt;.git/logs/refs/stash&lt;/code&gt; if the Git stash feature has been utilized within the repository as Git maintains a separate reflog for its stash functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Git Reflog is Needed?
&lt;/h2&gt;

&lt;p&gt;The primary function of Git reflog is to act as a safety net, enabling developers to recover lost commits or branches, reverse accidental changes, and navigate their repository's history effortlessly.&lt;/p&gt;

&lt;p&gt;In contrast to commands like git reset or git revert, which can irreversibly alter the repository's history or have broader impacts, Git reflog offers precise control. Developers can pinpoint specific moments in the repository's timeline and restore lost commits or branches without affecting unrelated parts of the history.&lt;/p&gt;

&lt;p&gt;Additionally, Git reflog provides transparency by revealing the sequence of operations and changes made to references in the repository. This visibility is crucial for understanding the repository's evolution over time and diagnosing development issues effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Use Git Reflog?
&lt;/h2&gt;

&lt;p&gt;To use git reflog, you simply have to use either &lt;code&gt;git reflog&lt;/code&gt; or &lt;code&gt;git reflog show&lt;/code&gt; and you'll get an output like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;a861fgd4b HEAD@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;: commit: Initial Commit
06f00264a HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add models
41d87a714 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add migrations
f80a505fb HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add serializers
8dbf0c9f2 &lt;span class="o"&gt;(&lt;/span&gt;origin/staging, staging&lt;span class="o"&gt;)&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
62170e3c3 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;5&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each reflog entry, in addition to its ordered index, is timestamped, facilitating filtering based on time.&lt;/p&gt;

&lt;p&gt;To view the date and time information along with reflog entries in a more readable format, you can use the following option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option displays the reflog entries with their corresponding timestamps in a local time format.&lt;/p&gt;

&lt;p&gt;The output in this case would be like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;72f3cbb50 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;Fri Mar 29 10:55:36 2024&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add missing created_at, updated_at
466c878c6 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;Thu Mar 28 16:15:21 2024&lt;span class="o"&gt;}&lt;/span&gt;: commit: Update BaseModelAdmin
3cb9c945d HEAD@&lt;span class="o"&gt;{&lt;/span&gt;Thu Mar 28 16:05:56 2024&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from ch/start-user-project to ch/minor-admin-changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see reflog entries with timestamps relative to the current time, rather than showing absolute timestamps with specific dates and times, you can use either of the following commands -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To see activity on HEAD, including timestamp&lt;/span&gt;
git reflog &lt;span class="nt"&gt;--relative-date&lt;/span&gt;

&lt;span class="c"&gt;#or&lt;/span&gt;

git reflog &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;relative
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Relative timestamps make it easier to quickly understand when a particular action occurred relative to the current time.&lt;/p&gt;

&lt;p&gt;The output, in this case, would look like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;937136cbb HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;}&lt;/span&gt;: commit: Update trigger &lt;span class="nb"&gt;time
&lt;/span&gt;ffe27973b HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;}&lt;/span&gt;: commit: Update task name
c7b76e8f3 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add slack alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also view the reflog entries for a specific branch(&lt;code&gt;staging&lt;/code&gt; in my case) with relative timestamps. Here's how you can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog show &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;relative &amp;lt;branch_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of the above command would look something like this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;8dbf0c9f2 &lt;span class="o"&gt;(&lt;/span&gt;origin/staging, staging&lt;span class="o"&gt;)&lt;/span&gt; staging@&lt;span class="o"&gt;{&lt;/span&gt;30 hours ago&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
62170e3c3 staging@&lt;span class="o"&gt;{&lt;/span&gt;31 hours ago&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
34502ef1d staging@&lt;span class="o"&gt;{&lt;/span&gt;3 days ago&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
63c9ac44a &lt;span class="o"&gt;(&lt;/span&gt;ch/ulj-weekly-application-summary-slack-message&lt;span class="o"&gt;)&lt;/span&gt; staging@&lt;span class="o"&gt;{&lt;/span&gt;4 days ago&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
2c6bbf64f staging@&lt;span class="o"&gt;{&lt;/span&gt;4 days ago&lt;span class="o"&gt;}&lt;/span&gt;: pull: Fast-forward
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, Git reflog provides insights into the history of the HEAD ref, which typically denotes the currently active branch in a repository.&lt;/p&gt;

&lt;p&gt;However, Git also maintains reflogs for other references beyond just the HEAD. These references encompass branches, tags, remotes, and even the Git stash, offering a comprehensive record of recent actions across various parts of the repository.&lt;/p&gt;

&lt;p&gt;The syntax for accessing a specific Git ref follows the pattern &lt;code&gt;name@{qualifier}&lt;/code&gt;, allowing developers to pinpoint specific reference updates. For instance, &lt;code&gt;otherbranch@{0}&lt;/code&gt; refers to the most recent update on the &lt;code&gt;otherbranch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The timestamp can also be used as a qualifier token, enabling precise retrieval of reflog entries based on some time-related criteria.&lt;/p&gt;

&lt;p&gt;Commonly used time qualifiers include &lt;code&gt;@{0}&lt;/code&gt; for the most recent update, &lt;code&gt;@{6.minutes.ago}&lt;/code&gt; for actions six minutes prior, and &lt;code&gt;@{&lt;/code&gt;&lt;a href="http://3.day" rel="noopener noreferrer"&gt;&lt;code&gt;3.day&lt;/code&gt;&lt;/a&gt;&lt;code&gt;.ago}&lt;/code&gt; for events three days in the past. These qualifiers can be combined (e.g., &lt;a href="http://1.day" rel="noopener noreferrer"&gt;&lt;code&gt;1.day&lt;/code&gt;&lt;/a&gt;&lt;code&gt;.3.hours.ago&lt;/code&gt;) and accept plural forms (e.g., &lt;code&gt;5.minutes.ago&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For example, to view reflog entries for the &lt;code&gt;develop&lt;/code&gt; branch from three days ago, you would execute -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog develop@&lt;span class="o"&gt;{&lt;/span&gt;3.days.ago&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;#or&lt;/span&gt;

git reflog show develop@&lt;span class="o"&gt;{&lt;/span&gt;3.days.ago&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command retrieves reflog entries specifically related to the &lt;code&gt;develop&lt;/code&gt; branch that occurred within the specified time window, enabling precise historical analysis and troubleshooting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common subcommands to git reflog
&lt;/h2&gt;

&lt;h3&gt;
  
  
  git reflog expire
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;expire&lt;/code&gt; sub-command in Git helps clean up old or unreachable reflog entries, which can make your repository history tidier.&lt;/p&gt;

&lt;p&gt;However, using this command without caution could accidentally delete important data. Usually, it's something Git handles internally rather than users directly dealing with it.&lt;/p&gt;

&lt;p&gt;To play it safe, you can run a "dry run" with the &lt;code&gt;-n&lt;/code&gt; or &lt;code&gt;--dry-run&lt;/code&gt; option before actually deleting anything. This lets you see which entries would be deleted without actually removing them, acting like a safety net.&lt;/p&gt;

&lt;p&gt;You can also set how long entries should stick around before expiring using the &lt;code&gt;--expire=time&lt;/code&gt; option or by changing a setting called &lt;code&gt;gc.reflogExpire&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  git reflog delete
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;delete&lt;/code&gt; command allows you to manually remove particular reflog entries. You can indicate which entry you want to delete by specifying its reference and qualifier.&lt;/p&gt;

&lt;p&gt;However, just like the &lt;code&gt;expire&lt;/code&gt; command, using &lt;code&gt;delete&lt;/code&gt; can lead to unintended data loss and isn't commonly used by regular users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the difference between git reflog and git log?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git reflog&lt;/code&gt; and &lt;code&gt;git log&lt;/code&gt; are two components provided by Git that allow us to peek into the repository’s commit history, logs, and reflogs. Sometimes, they show similar histories, especially when a developer does a bunch of local commits without syncing with the remote server. This similarity can cause confusion between &lt;code&gt;git reflog&lt;/code&gt; and &lt;code&gt;git log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, they are different and have different uses.&lt;/p&gt;

&lt;p&gt;The main difference is that the git log shows the public record of the repository's commit history, while git reflog is a private record specific to your workspace, showing your local commits.&lt;/p&gt;

&lt;p&gt;When you push, fetch, or pull changes, the git log gets copied to the Git repository. But git reflog doesn't get copied, so you can't see it in the copied repository unless you have access to the computer where the local repository is stored.&lt;/p&gt;

&lt;p&gt;The reflog is a file located in &lt;code&gt;.git\logs\refs\heads&lt;/code&gt; that keeps track of local commits for a specific branch. It doesn't include commits that might have been deleted by Git garbage collection.&lt;/p&gt;

&lt;p&gt;On the other hand, the git log shows a historical list of commits on a branch, starting from the most recent one and going back to the very first commit in the branch's history.&lt;/p&gt;

&lt;p&gt;To summarize the differences between these two git commands, take a look at the following table -&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;git reflog&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;git log&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tracking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tracks all reference updates (e.g., commits, branch operations, stash changes) in the local repository&lt;/td&gt;
&lt;td&gt;Tracks the commit history of a specific branch or set of commits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides a detailed history of recent actions, acting as a safety net for recovery&lt;/td&gt;
&lt;td&gt;Presents a chronological list of commits with details such as messages, authors, dates, and hashes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Specific to the local repository&lt;/td&gt;
&lt;td&gt;Reflects the commit history of the current branch or specified commits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Commonly used for troubleshooting, recovering lost work, and navigating recent changes&lt;/td&gt;
&lt;td&gt;Typically used for reviewing project history, understanding changes, and tracking codebase evolution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, Git maintains a reflog, which acts as a log of recent changes to your HEAD and branch references within the last few months (usually 90 days). This temporary history is continuously updated by Git whenever there's a modification to your branch tip.&lt;/p&gt;

&lt;p&gt;Additionally, the reflog command offers functionality to manage this log. You can use the "expire" sub-command to remove outdated reflog entries, ensuring the log doesn't become cluttered with old data. Similarly, the "delete" sub-command allows you to specify and delete specific entries from the reflog when needed.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>learning</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>State Machines in Practice: Implementing Solutions for Real Challenges</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Mon, 18 Mar 2024 17:55:57 +0000</pubDate>
      <link>https://forem.com/pragativerma18/state-machines-in-practice-implementing-solutions-for-real-challenges-3l76</link>
      <guid>https://forem.com/pragativerma18/state-machines-in-practice-implementing-solutions-for-real-challenges-3l76</guid>
      <description>&lt;p&gt;If you've studied engineering, you've probably heard about State Machines. But beyond the theory, you might not have seen how they're used. Did you know that State Machines play a role in many everyday applications? In this article, we'll refresh our understanding of State Machines and explore their practical applications. Plus, we'll learn how to implement them quickly using Python. Ready to dive in? Let's go!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;'State'&lt;/em&gt; is a common programming term that is experienced by all developers as they advance from beginning to intermediate-level programming. So, what exactly does the term "State" mean?&lt;/p&gt;

&lt;p&gt;In general, an object's state is merely the current snapshot of the object or a portion of it. Meanwhile, in computer science, a program's state is defined as its position about previously stored inputs. In this context, the term "state" is used in the same manner as it is in science: the state of an object, such as a gas, liquid, or solid, represents its current physical nature, and the state of a computer program reflects its current values or contents.&lt;/p&gt;

&lt;p&gt;The stored inputs are preserved as variables or constants in a computer program. While assessing the state of a program, developers might examine the values contained in these inputs. The state of the program may change while it runs - variables may change, and memory values may change. A control variable, such as one used in a loop, for example, changes the state of the program at each iteration. Examining the present state of a program may be used to test or analyze the codebase.&lt;/p&gt;

&lt;p&gt;In simpler systems, state management is frequently handled with if-else, if-then-else, try-catch statements, or boolean flags; however, this is useless when there are too many states imaginable in a program. They can lead to clunky, complicated code that is difficult to understand, maintain, and debug.&lt;/p&gt;

&lt;p&gt;One disadvantage of if-else-clauses or booleans is that they may get fairly extensive, and adding another state is difficult because it necessitates rewriting the code of many different classes.&lt;/p&gt;

&lt;p&gt;Let's build a video player for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be played when paused or stopped
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to play the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot play a video that is already playing.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be paused when it is playing
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to pause the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot pause a video that is not playing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be stopped when it is playing or paused
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to stop the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot stop a video that is not playing or paused&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code snippet is an if-else implementation of a simple video player application, where the three basic states are - playing, paused, and stopped. However, if we try to add more states, the code will rapidly become complex, bloated, repetitive, and hard to understand and test. Let’s see what the code looks like when adding another state ‘rewind’:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be played when it is paused or stopped or rewinding
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to play the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot play a video that is already playing.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be paused when it is playing or rewinding
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to pause the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot pause a video that is not playing or rewinding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# A video can only be stopped when it is playing or paused or rewinding
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to stop the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot stop a video that is not playing or paused or rewinding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# 4. A video can only be rewinded when it is playing or paused.
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rewind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="c1"&gt;# Make the call to rewind the video
&lt;/span&gt;           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_playing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_paused&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_stopped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
           &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_rewinding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cannot rewind a video that is not playing or paused&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
           &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the state pattern, you'd have to examine the program's current state throughout the code, including the update and draw methods. If you want to add a fourth state, such as a settings screen, you'll have to update the code of many distinct classes, which is inconvenient. This is where the idea of state machines comes in handy.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a state machine?
&lt;/h2&gt;

&lt;p&gt;State machines are not a novel concept in computer science; they are one of the basic design patterns utilized in the software business. It is more system-oriented than coding-oriented and is used to model around use cases.&lt;/p&gt;

&lt;p&gt;Let's look at a simple real-life example of hiring a cab through Uber:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When you initially launch the program, it takes you to the home screen, where you type in your destination in the search area.&lt;/li&gt;
&lt;li&gt;Once the right location has been identified, Uber displays recommended travel options such as Pool, Premier, UberGo, Uber XL, and others, along with a pricing estimate.&lt;/li&gt;
&lt;li&gt;The trip is confirmed and a driver is assigned once you select the payment option and press the 'Confirm' button with the specified journey time if necessary.&lt;/li&gt;
&lt;li&gt;Uber now displays a map on which you can locate your driver.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Screen 1 is the first screen that all users in this use case see, and it is self-contained. Screen 2 is reliant on Screen 1, and you will not be able to go to Screen 2 until you give accurate data on Screen 1. Likewise, screen 3 is dependent on screen 2, while screen 4 is dependent on screen 3. If neither you nor your driver cancels your trip, you'll be moved to screen 4, where you won't be able to plan another trip until your current one ends.&lt;/p&gt;

&lt;p&gt;Let's say it's raining severely and no driver accepts your trip or no available driver in your region is found to finish your travel; an error notification warning you of driver unavailability shows, and you remain on screen 3. You may still return to screen 2, screen 1, and even the very first screen.&lt;/p&gt;

&lt;p&gt;You are in a different step of the cab reservation process, and you may only go to the next level if a specified action in the current stage is successful. For example, if you input the wrong location on screen 1, you won't be able to proceed to screen 2, and you won't be able to proceed to screen 3 unless you pick a travel option on screen 2, but you may always return to the previous stage unless your trip is already booked.&lt;/p&gt;

&lt;p&gt;In the above example, we've divided the cab booking process into several activities, each of which may or may not be authorized to call another activity based on the status of the booking. A state machine is used to model this. In principle, each of these stages/states should be autonomous, with one summoning the next only after the current one has been finished, successfully or otherwise.&lt;/p&gt;

&lt;p&gt;In more technical words, the state machine enables us to split down a large complicated action into a succession of separate smaller activities, such as the cab booking activity in the preceding example.&lt;/p&gt;

&lt;p&gt;Events connect smaller tasks, and shifting from one state to another is referred to as transition. We normally conduct some actions after changing from one state to another, such as creating a booking in the back end, issuing an invoice, saving user analytics data, capturing booking data in a database, triggering payment after the trip is finished, and so on.&lt;/p&gt;

&lt;p&gt;Hence, the general formula for a state machine can be given as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Current State + Some Action / Event= Another State&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s see what a state machine designed for a simple video player application would look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jyg0q7u49tjae7mxr93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jyg0q7u49tjae7mxr93.png" alt="State Diagram for a simple video player application" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we can implement it in code using transitions as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Machine&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="c1"&gt;# Define the states
&lt;/span&gt;   &lt;span class="n"&gt;PLAYING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;playing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;PAUSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paused&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;STOPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stopped&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;

       &lt;span class="c1"&gt;# Define the transitions
&lt;/span&gt;       &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="c1"&gt;# 1. A video can only be played when it is paused or stopped.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;play&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;play&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="c1"&gt;# 2. A video can only be paused when it is playing.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pause&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="c1"&gt;# 3. A video can only be stopped when it is playing or paused.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
       &lt;span class="p"&gt;]&lt;/span&gt;

       &lt;span class="c1"&gt;# Create the state machine
&lt;/span&gt;       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Machine&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transitions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in case, we want to add another state, say rewind, we can do that easily as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjo7fsps54xk2ot82emm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjo7fsps54xk2ot82emm.png" alt="State diagram with rewind state" width="800" height="579"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Machine&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="c1"&gt;# Define the states
&lt;/span&gt;   &lt;span class="n"&gt;PLAYING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;playing&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;PAUSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;paused&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;STOPPED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stopped&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;REWINDING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rewinding&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;# new
&lt;/span&gt;
   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;

       &lt;span class="c1"&gt;# Define the transitions
&lt;/span&gt;       &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="c1"&gt;# 1. A video can only be played when it is paused or stopped.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;play&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;play&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;play&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REWINDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;# new
&lt;/span&gt;           &lt;span class="c1"&gt;# 2. A video can only be paused when it is playing.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pause&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pause&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REWINDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;# new
&lt;/span&gt;           &lt;span class="c1"&gt;# 3. A video can only be stopped when it is playing or paused.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REWINDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;# new
&lt;/span&gt;           &lt;span class="c1"&gt;# 4. A video can only be rewinded when it is playing or paused.
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rewind&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PLAYING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REWINDING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;#new
&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;trigger&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rewind&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PAUSED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REWINDING&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;# new
&lt;/span&gt;       &lt;span class="p"&gt;]&lt;/span&gt;

       &lt;span class="c1"&gt;# Create the state machine
&lt;/span&gt;       &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Machine&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;transitions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transitions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STOPPED&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rewind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
       &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, we can see how state machines can simplify a complex implementation and save us from writing incorrect code. Having learned the capabilities of state machines, it’s now important to understand why and when to use state machines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &amp;amp; When to Use State Machines?
&lt;/h2&gt;

&lt;p&gt;State Machines can be utilized in applications that have distinct states. Each stage can lead to one or more subsequent states, as well as end the process flow. A State Machine employs user input or in-state computations to choose which state to enter next.&lt;/p&gt;

&lt;p&gt;Many applications necessitate an "initialize" stage, followed by a default state that allows for a wide range of actions. Previous and present inputs, as well as states, can all have an impact on the actions that are executed. Clean-up measures can then be carried out when the system is "shut down."&lt;/p&gt;

&lt;p&gt;A state machine can help us conceptualize and manage those units more abstractly if we can break down a hugely complex job into smaller, independent units, where we simply need to describe when a state can transition to another state and what happens when the transition occurs. We don't need to be concerned with how the transition occurs after setup. After that, we only need to think about when and what, not how.&lt;/p&gt;

&lt;p&gt;Furthermore, state machines let us see the entire state process in a very predictable way; once transitions are set, we don't have to worry about mismanagement or erroneous state transitions; the improper transition may occur only if the state machine is configured properly. We have a comprehensive view of all states and transitions in a state machine.&lt;/p&gt;

&lt;p&gt;If we don't use a state machine, we are either unable to visualize our systems in various possible states, or we are knowingly or unknowingly coupling our components tightly together, or we are writing many if-else conditions to simulate state transitions, which complicates unit and integration testing because we must ensure that all test cases are written to validate the possibility of all the conditions and branching used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of State Machines
&lt;/h2&gt;

&lt;p&gt;State machines, in addition to their ability to develop decision-making algorithms, are functional forms of application planning. As applications get more complex, the need for effective design grows.&lt;/p&gt;

&lt;p&gt;State diagrams and flowcharts are useful and occasionally essential throughout the design process. State Machines are important not just for application planning but are also simple to create.&lt;/p&gt;

&lt;p&gt;Following are some of the major advantages of state machines in modern-day computing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It helps you eliminate hard coding conditions. On your behalf, the state machine abstracts all logic related to states and transitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State machines often have a finite number of states with definite transitions, making it simple to identify which transition/data/event triggered the present state of a request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After establishing a state machine, developers may concentrate on building actions and preconditions. With sufficient validation and preconditioning, state machines restrict out-of-order operations. As in the Uber example, a driver cannot be rewarded until the voyage is done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State machines can be quite easy to maintain. The actions taken during each transition are logically independent of one another. As a result, the corresponding code can be isolated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State machines are less prone to change and are more stable. It becomes much easier to maintain such systems if the current and future use cases are very obvious.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disadvantages of State Machines
&lt;/h2&gt;

&lt;p&gt;Not everything about state machines is good, they can sometimes lead to drawbacks and challenges too. Here are some of the common problems with state machines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;State machines are usually synchronous. So, if you need asynchronous background API calls/job execution, you'll have to weigh the pros and cons carefully before deciding on the best option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code can quickly get jumbled. Because state machines are data-driven, your product team may ask you to execute different transitions from the same state based on different data/input parameters. As a result, this type of demand may result in multiple transitions with a clumsy precondition check. It is entirely dependent on the product and the machine's current configuration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you need to load balance state machine instances, go with the one that has persistence enabled; otherwise, you'll need to implement your persistence layer and necessary validations to ensure that multiple requests fired at separate state machine instances produce consistent results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because there are few resources or communities dedicated to distinct state machine implementations, assistance may be limited once you've chosen a library.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Things to keep in mind when using State Machines
&lt;/h2&gt;

&lt;p&gt;When using a state machine, your system should ideally have two logical components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the state machine/workflow system itself&lt;/li&gt;
&lt;li&gt;the business logic contained in one or more services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The state machine may be thought of as the infrastructure that drives state transitions; it verifies state transitions and executes configured actions before, during, and after a transition; however, it should not know what business logic is done in those actions.&lt;/p&gt;

&lt;p&gt;So, in general, it's a good idea to isolate the state machine from the core business logic by using correct abstractions; otherwise, managing the code would be a nightmare.&lt;/p&gt;

&lt;p&gt;Here are some other real-life scenarios where we need to employ state machine logic with caution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A state machine is more than just states, transitions, and actions. It should also be capable of defining a border around a state change. A transition can only be successful in particular cases if it is triggered by a trustworthy system or user. There might be a variety of similar situations. As a consequence, we should be able to develop appropriate state transition guarding logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We commonly end up with many processes for the same business entity that can run concurrently. In such cases, one process does not obstruct other workflows; they may or may not be triggered concurrently, but they may coexist; the second workflow may begin from one of the first workflow's eligible phases, after which it may branch off and work independently. This sort of use case is established by the business; not every organization will have it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In principle, workflow systems are independent of the business domain. As a consequence, in the same workflow system, many processes with no link to the same business organization can be established. They may have a shared or distinct starting point, depending on whether the workflow system enables multiple starting points.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When numerous separate workflows are formed in the same workflow system, you get a global picture of all business processes running across various business entities in your system. Depending on the business use cases, different processes may also have certain identical stages.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical or real-life use cases for state machines:
&lt;/h2&gt;

&lt;p&gt;Following are some of the practical applications that benefit from the concept of state machines in our daily lives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single-page or tabbed dialogue boxes A tab in the conversation box represents each state. A user can initiate a state transition by selecting a certain tab. The status for each tab includes any actions that the user can take.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A self-service banking machine (ATM). In this application, states such as waiting for user input, confirming the needed amount against the account balance, distributing the money, printing the receipt, and so on are all conceivable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A software that takes a single measurement, stores it in memory, and then waits for the user to take another action. This program's steps include waiting for user input, performing the measurement, recording the data, displaying the results, and so on. Configuring ETL Jobs, for example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;State machines are commonly used for designing user interfaces. While designing a user interface, distinct user actions shift the user interface into separate processing segments. Each of these elements will function as a state in the State Machine. These segments can either lead to another segment for further processing or wait for another user event. In this scenario, the State Machine monitors the user to determine what action they should take next.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you purchase something from an online e-commerce site, for example, it goes through various phases, such as Ordered, Packed, Shipped, Cancelled, Delivered, Paid, Refunded, and so on. The transition occurs automatically as things move through a warehouse or logistics center and are scanned at various stages, such as when a user cancels or wants a refund.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process testing is another typical application for State Machines. In this example, each stage of the process is represented by a state. Depending on the results of each state's exam, a separate state may be declared. This might happen frequently if the process under examination is thoroughly studied.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The notion of state machines is extremely useful in programming. It not only streamlines the process of developing more complicated use case apps but also reduces the development work necessary. It provides a more simple and elegant grasp of modern-day events and when correctly applied, may work miracles.&lt;/p&gt;




&lt;p&gt;If you find this insightful, do let me know your views in the comments. Also, any kind of feedback is welcome. In case you want to connect with me, follow the links below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/pragativerma18/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://github.com/PragatiVerma18/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | &lt;a href="https://twitter.com/pragati_verma18" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>python</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>HTTP Status Codes That Will Make You Think</title>
      <dc:creator>Pragati Verma</dc:creator>
      <pubDate>Sun, 24 Sep 2023 18:15:02 +0000</pubDate>
      <link>https://forem.com/pragativerma18/http-status-codes-that-will-make-you-think-5mc</link>
      <guid>https://forem.com/pragativerma18/http-status-codes-that-will-make-you-think-5mc</guid>
      <description>&lt;p&gt;Last year, I wrote an &lt;a href="https://dev.to/pragativerma18/youre-not-using-http-status-codes-right-pc6"&gt;article&lt;/a&gt; on how we might be using some of the HTTP status codes wrong, and this time I discovered some HTTP status codes that we don't use that commonly, but they can have fascinating use cases.&lt;/p&gt;

&lt;p&gt;So, in this article, we will discuss some HTTP status codes that will make you think. Let's get started!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F1FDeKGQHaUcAAAAC%2Ffriends-rachel.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F1FDeKGQHaUcAAAAC%2Ffriends-rachel.gif%2520align%3D" alt="Friends Rachel GIF - Friends Rachel Green GIFs" width="498" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It would be more fun if try to guess what the status code means while you read the heading! 😉&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  103 Early Hints 🫣
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FUdl9lb_lQk4AAAAC%2Fmaybe-take-a-hint-tyler-oakley.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FUdl9lb_lQk4AAAAC%2Fmaybe-take-a-hint-tyler-oakley.gif%2520align%3D" alt="Maybe Take A Hint Tyler Oakley GIF - Maybe Take A Hint Tyler Oakley Hint Hint GIFs" width="498" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The 103 Early Hints HTTP status code is a bit unusual but pretty interesting. It's like a friendly advance notice from a web server to your browser. When a server sends a 103 code, it's saying, "Hey, I'm going to send you a bunch of stuff, and here's a sneak peek to get you started."&lt;/p&gt;

&lt;p&gt;It's kind of like when you're at a restaurant, and the chef sends out a little appetizer before your main course. In this case, the server is letting your browser know that more data is on the way, so your browser can start preparing to receive it. It's all about optimizing the loading process and making your web experience smoother.&lt;/p&gt;

&lt;p&gt;Its benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Loading:&lt;/strong&gt; Provides early hints to browsers, allowing them to start fetching critical resources sooner, leading to faster page rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced User Experience:&lt;/strong&gt; Reduces perceived loading times, resulting in a better user experience and higher engagement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimized Resource Fetching:&lt;/strong&gt; Prioritizes essential assets, optimizing the loading of above-the-fold content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Round-Trips:&lt;/strong&gt; Minimizes the need for additional requests, reducing latency and loading times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bandwidth Savings:&lt;/strong&gt; Avoids fetching unnecessary resources, saving bandwidth for both users and servers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  300 Multiple Choices
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fua4iXzpdLDEAAAAC%2Felmo-pass-out.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2Fua4iXzpdLDEAAAAC%2Felmo-pass-out.gif%2520align%3D" alt="Elmo Pass Out GIF - Elmo Pass Out Black Out GIFs" width="400" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 300, "Multiple Choices," is used to indicate that the requested resource has multiple representations available, each with its own specific location (URI), and the user or client must choose one.&lt;/p&gt;

&lt;p&gt;When a server returns a 300 status code, it typically includes a "Location" header in the response with a list of URIs for the alternative representations of the resource. The client can then decide which URI to follow based on user preferences or application logic.&lt;/p&gt;

&lt;p&gt;For example, if a client requests a resource like a document, and the server has multiple versions of that document in different formats (e.g., HTML, PDF, plain text), it can respond with a 300 status code and provide URIs for each version. The client can then prompt the user to choose the preferred format, or it can use its own logic to make the selection.&lt;/p&gt;

&lt;p&gt;The 300 status code is relatively rare in typical web interactions and is mainly used in scenarios where content negotiation is necessary to determine the best representation of a resource based on user or application requirements.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/300" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  303 See Other 👀
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FHRIndWP0nXcAAAAC%2Fchandler-friends.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FHRIndWP0nXcAAAAC%2Fchandler-friends.gif%2520align%3D" alt="Chandler Friends GIF - Chandler Friends Breakup GIFs" width="360" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 303 See Other is a redirection status code used to instruct a web client (usually a web browser) to perform a GET request to a different URI. It indicates that the resource the client requested can be found at a different location, and the client should retrieve it from there.&lt;/p&gt;

&lt;p&gt;This status code is like a signpost that says, "You asked for something, but it's not here. Go check somewhere else!" It's a way for a web server to tell your browser that the resource you're looking for can be found at a different location or URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F1jOsDJOiO04AAAAd%2Fim-gonna-go-be-anywhere-im-going-to-go-away.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F1jOsDJOiO04AAAAd%2Fim-gonna-go-be-anywhere-im-going-to-go-away.gif%2520align%3D" alt="Im Gonna Go Be Anywhere Im Going To Go Away GIF - Im Gonna Go Be Anywhere Im Going To Go Away Be Anywhere Else GIFs" width="640" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait, doesn't that sound a lot like HTTP status code 302 Found?&lt;/p&gt;

&lt;p&gt;HTTP status codes 302 and 303 both deal with redirection, but they serve different purposes. The key distinction lies in the nature of the redirection. The 302 status code indicates a temporary redirection, where the requested resource is temporarily available at a different URI.&lt;/p&gt;

&lt;p&gt;In contrast, the 303 status code signifies a more explicit redirection, instructing the client to make a new GET request to the alternative URI for the requested resource.&lt;/p&gt;

&lt;p&gt;While 302 implies that future requests may still be directed to the original URI, 303 is often used when you want to ensure that subsequent requests for the same resource always go to the new URI, making it particularly useful for certain web forms and data submissions.&lt;/p&gt;

&lt;p&gt;For example, after successfully submitting a form on a website, the server might respond with a 303 code and a "Location" header pointing to a new URI that displays a thank-you message or a confirmation page. This ensures that refreshing the confirmation page won't result in a duplicate form submission. The client is instructed to make a GET request to the new URI to retrieve the result or view the confirmation, decoupling it from the initial POST request.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h3&gt;
  
  
  406 Not Acceptable ❌
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FkVwXPYmSvQAAAAAC%2Fthis-is-unacceptable.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FkVwXPYmSvQAAAAAC%2Fthis-is-unacceptable.gif%2520align%3D" alt="This Is Unacceptable GIF - This Is Unacceptable No Good GIFs" width="498" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 406 Not Acceptable is returned by a web server when a client's request specifies certain response criteria, such as acceptable media types (content types), languages, or character sets, that the server cannot fulfill based on the available resources. In other words, the server cannot provide a response that matches the client's specified preferences.&lt;/p&gt;

&lt;p&gt;For example, if a client sends an HTTP request header indicating that it only accepts responses in a particular language or content type, and the server does not have the requested content in that language or format, it would respond with a 406 status code.&lt;/p&gt;

&lt;p&gt;The 406 status code is essentially a way for the server to communicate to the client that it cannot meet the specific content requirements specified in the request, and the client may need to adjust its preferences or handle the situation accordingly, such as by requesting a different content type or language.&lt;/p&gt;

&lt;p&gt;Sounds a lot like 404 Not Found no? No, it doesn't, if you read it carefully, the 406 status code is about the server having the resource but not in the requested format, while the 404 status code is about the server not finding the resource at all.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/303" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h3&gt;
  
  
  409 Conflict ⚔️
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FKjImwF1A5dYAAAAC%2Fcat-kitty.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FKjImwF1A5dYAAAAC%2Fcat-kitty.gif%2520align%3D" alt="Cat Kitty GIF - Cat Kitty Kitten GIFs" width="498" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 409, "Conflict," is used to indicate that the request could not be completed due to a conflict with the current state of the target resource. This status code typically arises in scenarios involving concurrent updates or conflicting changes to a resource.&lt;/p&gt;

&lt;p&gt;For example, if two users attempt to modify the same piece of data simultaneously, a conflict can occur. In this case, the server may respond with a 409 status code to inform the clients that their requests cannot be processed because of the conflicting changes.&lt;/p&gt;

&lt;p&gt;The response often includes additional information or guidance on how to resolve the conflict, such as which resource state caused the conflict or how clients can retry their requests after addressing the conflict. It is commonly used in web applications, especially those with collaborative editing or version control features, to manage data consistency in situations where multiple parties can modify the same resource.&lt;/p&gt;

&lt;p&gt;Did you think of 400 Bad Request while reading the above case? Well, to clarify that, while a 400 error points to issues with the request itself, a 409 error points to conflicts arising from the state of the resource being modified.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/409" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  410 Gone 🪄
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FO2RBK9klEMYAAAAC%2Fhomer-simpson-homer.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FO2RBK9klEMYAAAAC%2Fhomer-simpson-homer.gif%2520align%3D" alt="Homer Disappears Into A Hedge GIF - Homer Simpson Homer Disappears GIFs" width="498" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 410, "Gone," is used to indicate that a previously available resource on the server is no longer accessible and has been intentionally removed or permanently deleted. Unlike the 404 status code, which simply indicates that a resource is not found, the 410 status code explicitly conveys that the resource existed in the past but has now been deliberately taken down, and there is no expectation of it becoming available again in the future.&lt;/p&gt;

&lt;p&gt;Website administrators and developers may use the 410 status code when they want to inform both clients and search engines that a resource, such as a webpage or an API endpoint, has been permanently discontinued. This can be useful for maintaining the accuracy of search engine results and informing users that the resource they were seeking is no longer accessible.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/410" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  417 Expectation Failed 😞
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FcXYPZhsqJlkAAAAC%2Fchien-perplexe.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FcXYPZhsqJlkAAAAC%2Fchien-perplexe.gif%2520align%3D" alt="Chien Perplexe GIF - Chien Perplexe Dog GIFs" width="498" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 417, "Expectation Failed," is used to indicate that a server cannot meet the client's expectations specified in the "Expect" request header of the HTTP request.&lt;/p&gt;

&lt;p&gt;The "Expect" header is typically used to define certain expectations the client has about how the server should handle the request, such as requesting that the server respond with a specific status code or comply with certain protocol extensions.&lt;/p&gt;

&lt;p&gt;When a server encounters an "Expect" header that it cannot fulfill, it responds with a 417 status code. This can happen, for example, if the client expects the server to support a specific authentication method or protocol extension, but the server cannot meet that expectation.&lt;/p&gt;

&lt;p&gt;The 417 status code is relatively rare and may not be encountered in everyday web browsing.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/417" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  418 I'm a teapot 🫖
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FrpN1SBkINroAAAAC%2Fcuteniallhoran-niallhoran.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FrpN1SBkINroAAAAC%2Fcuteniallhoran-niallhoran.gif%2520align%3D" alt="Cuteniallhoran GIF - Cuteniallhoran Niallhoran Cute GIFs" width="498" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HTTP status code 418, "I'm a teapot," is an April Fools' joke and is not a standard HTTP status code. It was introduced in RFC 2324, a document titled "Hyper Text Coffee Pot Control Protocol," which is not a serious HTTP specification but rather a humorous and playful one.&lt;/p&gt;

&lt;p&gt;This status code was intended to be a joke and not meant for actual use in web development or communication between servers and clients. It is not recognized or implemented by web servers or browsers for practical purposes.&lt;/p&gt;

&lt;p&gt;So, if you encounter the "418 I'm a teapot" status code in any context, it's likely being used for fun or as a humorous way to communicate that the request is not valid or should not be taken seriously.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  422 Unprocessable Content 😵‍💫
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FZ6ktpgNXOz4AAAAC%2Ffrustrated-frustrating.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FZ6ktpgNXOz4AAAAC%2Ffrustrated-frustrating.gif%2520align%3D" alt="Frustrated Frustrating GIF - Frustrated Frustrating Stitch GIFs" width="248" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might know about the HTTP status code 400, "Bad Request," which indicates that the server cannot process the client's request due to issues with the request itself, such as malformed syntax or missing required parameters. It signifies that the server does not understand or cannot fulfill the request due to client errors.&lt;/p&gt;

&lt;p&gt;On the other hand, HTTP status code 422, "Unprocessable Entity," is used when the server can understand the client's request but cannot process it because the request's content, such as data or input, is semantically incorrect, syntactically invalid, or violates validation rules set by the server. It specifically addresses issues with the request's content, making it a more suitable choice when the request entity is problematic but not due to generic syntax errors.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  451 Unavailable For Legal Reasons 👩‍⚖️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F4kk5gX8Vf34AAAAC%2Fyouknowthelaw-ninjaassassin.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F4kk5gX8Vf34AAAAC%2Fyouknowthelaw-ninjaassassin.gif%2520align%3D" alt="Youknowthelaw Ninjaassassin GIF - Youknowthelaw Ninjaassassin Ozunu GIFs" width="498" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The HTTP status code 451, "Unavailable For Legal Reasons," is used to indicate that a server has received a request for a resource, but it refuses to fulfill the request due to legal restrictions or legal censorship.&lt;/p&gt;

&lt;p&gt;This status code is typically used when a government or legal authority has mandated the removal or blocking of specific content, and the server must comply with these legal requirements.&lt;/p&gt;

&lt;p&gt;The name "451" is a reference to Ray Bradbury's novel "Fahrenheit 451," in which books are banned and burned by the government. The choice of this status code name symbolizes the idea of content being "unavailable for legal reasons."&lt;/p&gt;

&lt;p&gt;When a server responds with a 451 status code, it may also include additional information in the response, such as a description of the legal restrictions or a reference to the relevant laws or regulations.&lt;/p&gt;

&lt;p&gt;The 451 status code is relatively recent in the HTTP standard and reflects the growing awareness of legal and censorship-related issues on the internet. Its use is typically associated with cases where access to certain online content is restricted due to legal compliance.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/451" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more info.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FUePL7oHsL8sAAAAC%2Fglee-finn-hudson.gif%2520align%3D" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2FUePL7oHsL8sAAAAC%2Fglee-finn-hudson.gif%2520align%3D" alt="Glee Finn Hudson GIF - Glee Finn Hudson I Realize I Still Have A Lot To Learn GIFs" width="498" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot more HTTP status codes that we don't really use commonly but they exist for specific purposes. I hope that you found this article helpful.  &lt;/p&gt;

&lt;p&gt;Do let me know if you used any of the above HTTP status codes in any interesting use case.  &lt;/p&gt;

&lt;p&gt;Keep reading! 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>computerscience</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
