<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Naveen P.N's Tech Blog]]></title><description><![CDATA[Naveen P.N's Tech Blog]]></description><link>https://blog.naveenpn.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 03:43:35 GMT</lastBuildDate><atom:link href="https://blog.naveenpn.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Key Problems Microsoft Fabric Solves]]></title><description><![CDATA[Data Silos Across Tools
Problem Organizations use many separate tools for

ETL (Data Factory),

Warehousing (Synapse/Snowflake),

Big Data (Databricks/Hadoop),

Visualization (Power BI/Tableau), etc.
]]></description><link>https://blog.naveenpn.com/key-problems-microsoft-fabric-solves</link><guid isPermaLink="true">https://blog.naveenpn.com/key-problems-microsoft-fabric-solves</guid><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 03 Mar 2026 07:22:36 GMT</pubDate><content:encoded><![CDATA[<h2><strong>Data Silos Across Tools</strong></h2>
<p><strong>Problem</strong> Organizations use many separate tools for</p>
<ul>
<li><p>ETL (Data Factory),</p>
</li>
<li><p>Warehousing (Synapse/Snowflake),</p>
</li>
<li><p>Big Data (Databricks/Hadoop),</p>
</li>
<li><p>Visualization (Power BI/Tableau), etc.</p>
</li>
</ul>
<p>Data gets copied, moved, and duplicated across systems → leading to data silos.</p>
<p><strong>Fabric Solution:</strong> Brings all workloads (Data Factory, Data Engineering, Data Science, Data Warehouse, Real-Time Analytics, Power BI) into one unified SaaS platform.</p>
<p><strong>Impact :</strong> No need to maintain multiple vendors, multiple bills, or custom integrations.</p>
<h2><strong>Data Duplication &amp; Movement</strong></h2>
<p><strong>Problem</strong> : In traditional setups, the same data is stored in multiple places (data lake + warehouse + BI extracts). Moving large data sets is costly, slow, and error-prone.</p>
<ul>
<li><strong>Fabric Solution</strong>: Introduces OneLake (a single data lake for the whole organization) with Delta Lake format. All workloads access the same data without copying.</li>
</ul>
<p><strong>Impact</strong>: Reduces storage cost, improves performance, and ensures one source of truth.</p>
<h2><strong>Complex Governance &amp; Security</strong></h2>
<p><strong>Problem:</strong> Each system has separate security, compliance, and governance policies → very hard to manage at enterprise scale.</p>
<ul>
<li><p><strong>Fabric Solution: Provides centralized governance and role-based access integrated with Microsoft Entra ID.</strong></p>
</li>
<li><p><strong>Impact: One set of policies, lineage, audit, and compliance rules apply across the platform.</strong></p>
</li>
</ul>
<h2><strong>Slow Time to Insights</strong></h2>
<p><strong>Problem:</strong> Data teams spend too much time building pipelines, moving data between systems, and waiting for refreshes.</p>
<p><strong>Fabric Solution:</strong> End-to-end integration + AI-powered Copilot to generate queries, transformations, and reports quickly.</p>
<p><strong>Impact:</strong> Reduces time from raw data → actionable insight dramatically.</p>
<h3><strong>Fragmented User Experience</strong></h3>
<p><strong>Problem:</strong> Different teams (engineers, scientists, analysts, executives) use different tools → collaboration is poor, and outputs are disconnected.</p>
<ul>
<li><p><strong>Fabric Solution</strong>: Provides dedicated experiences for each role within the same platform.</p>
</li>
<li><p><strong>Impact:</strong> Everyone works with the same data, using the tool best suited to their skillset.</p>
</li>
</ul>
<h3><strong>High Cost &amp; Vendor Complexity</strong></h3>
<p><strong>Problem:</strong> Companies juggle multiple contracts (Snowflake, Databricks, Informatica, Tableau, etc.), leading to high costs and integration headaches.</p>
<ul>
<li><p><strong>Fabric Solution: Single SaaS billing model (pay as you go), included with Microsoft ecosystem (Power BI, Azure).</strong></p>
</li>
<li><p><strong>Impact: Lower TCO (total cost of ownership), simpler procurement, and cost transparency.</strong></p>
</li>
</ul>
<p><strong>Microsoft Fabric solves:</strong></p>
<ul>
<li><p><strong>Data silos → Unified platform</strong></p>
</li>
<li><p><strong>Duplication → OneLake storage</strong></p>
</li>
<li><p><strong>Governance complexity → Centralized security</strong></p>
</li>
<li><p><strong>Slow insights → AI + end-to-end workflows</strong></p>
</li>
<li><p><strong>Fragmented tools → Role-based experiences</strong></p>
</li>
<li><p><strong>High costs → Single SaaS model</strong></p>
</li>
</ul>
<table style="min-width:594px"><colgroup><col style="min-width:25px"></col><col style="width:333px"></col><col style="width:236px"></col></colgroup><tbody><tr><td><p>Aspect</p></td><td><p>Before Fabric (Traditional Setup)</p></td><td><p>After Fabric (With Microsoft Fabric)</p></td></tr><tr><td><p>Data Storage</p></td><td><p>Multiple systems (Data Lake, Warehouse, BI extracts). Data copied across tools → duplication &amp; cost.</p></td><td><p>OneLake (single data lake for all workloads). No duplication, single source of truth.</p></td></tr><tr><td><p>Tooling</p></td><td><p>Separate tools: Data Factory (ETL), Synapse/Snowflake (warehouse), Databricks (big data), Power BI/Tableau (visualization).</p></td><td><p>Unified SaaS platform: Data Factory, Engineering, Science, Warehouse, Real-Time, Power BI all in one.</p></td></tr><tr><td><p>Governance &amp; Security</p></td><td><p>Different governance models for each tool → inconsistent policies, hard compliance.</p></td><td><p>Centralized governance &amp; security (Microsoft Entra ID). One set of rules across the platform.</p></td></tr><tr><td><p>Data Movement</p></td><td><p>Data moved between systems → slow, costly, error-prone.</p></td><td><p>No movement needed → all workloads work directly off OneLake.</p></td></tr><tr><td><p>User Experience</p></td><td><p>Fragmented: engineers, analysts, scientists, and business users work in silos.</p></td><td><p>Role-based experiences in the same platform → seamless collaboration.</p></td></tr><tr><td><p>Time to Insights</p></td><td><p>Long cycles: ingest → transform → copy → analyze → visualize.</p></td><td><p>Faster: end-to-end workflows + AI Copilot for queries, reports, transformations.</p></td></tr><tr><td><p>Costs</p></td><td><p>Multiple vendors, contracts, and storage costs.</p></td><td><p>Single SaaS billing (pay-as-you-go). Lower TCO (Total Cost of Ownership).</p></td></tr><tr><td><p>AI Integration</p></td><td><p>Add-ons needed (custom ML integrations, separate tools).</p></td><td><p>Built-in AI &amp; Copilot to accelerate development and insights.</p></td></tr></tbody></table>]]></content:encoded></item><item><title><![CDATA[Unity Catalog vs Hive Metastore]]></title><description><![CDATA[What is Hive Metastore

Legacy metadata store for tables and schemas

Linked to single Databricks workspace

Stores based info : table names, locations, schema


Limitation

No centralized security across workspaces

No column level access control

H...]]></description><link>https://blog.naveenpn.com/unity-catalog-vs-hive-metastore</link><guid isPermaLink="true">https://blog.naveenpn.com/unity-catalog-vs-hive-metastore</guid><category><![CDATA[data-engineering]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 17 Jul 2025 08:19:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752857707384/9649c465-8ed1-4efc-a0bf-60eb1b8e09e4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-what-is-hive-metastore">What is Hive Metastore</h1>
<ul>
<li><p>Legacy metadata store for tables and schemas</p>
</li>
<li><p>Linked to single Databricks workspace</p>
</li>
<li><p>Stores based info : table names, locations, schema</p>
</li>
</ul>
<p><strong>Limitation</strong></p>
<ul>
<li><p>No centralized security across workspaces</p>
</li>
<li><p>No column level access control</p>
</li>
<li><p>Harder to manage data governance at scale</p>
</li>
</ul>
<h1 id="heading-what-is-unity-catalog">What is Unity Catalog</h1>
<ul>
<li><p>Centralized metadata + security layer across all workspaces</p>
</li>
<li><p>Fine-grained access control : tables, columns, rows</p>
</li>
<li><p>Built-in data lineage tracking</p>
</li>
<li><p>Supports multi-cloud environments (AWS, Azure, GCP)</p>
</li>
<li><p>One place to manage permissions, audits, and discovery across your entire organization.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Advanced Python Dependency Injection with Pydantic and FastAPI]]></title><description><![CDATA[Introduction

Modern backend architectures demand modular, maintainable, and testable code. One of the cornerstones of achieving this is Dependency Injection (DI) — a software design pattern that helps decouple object creation from business logic, ma...]]></description><link>https://blog.naveenpn.com/advanced-python-dependency-injection-with-pydantic-and-fastapi</link><guid isPermaLink="true">https://blog.naveenpn.com/advanced-python-dependency-injection-with-pydantic-and-fastapi</guid><category><![CDATA[#ScalableBackend ]]></category><category><![CDATA[Python]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[pydantic]]></category><category><![CDATA[dependency injection]]></category><category><![CDATA[#ModernPython]]></category><category><![CDATA[AsyncApi]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[#pythonwebdevelopment]]></category><category><![CDATA[Backend Engineering]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Fri, 20 Jun 2025 11:46:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750827418037/313f5547-be8c-414f-b64d-e7b475c652fa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<blockquote>
<p>Modern backend architectures demand modular, maintainable, and testable code. One of the cornerstones of achieving this is <strong>Dependency Injection (DI)</strong> — a software design pattern that helps decouple object creation from business logic, making applications easier to scale, test, and extend.</p>
</blockquote>
<p>While traditional frameworks like Django use settings modules and class-based views for configuration and service management, <strong>FastAPI</strong> takes this a step further with its native, lightweight, and elegant dependency injection system built on <strong>function parameters</strong> and Python’s <code>async</code> capabilities.</p>
<p>When combined with <strong>Pydantic</strong>, FastAPI’s preferred data validation and parsing library, it enables powerful, type-safe, and scalable dependency management — ideal for modern, asynchronous web services.</p>
<p>This guide will take you through:</p>
<ul>
<li><p>What Dependency Injection is</p>
</li>
<li><p>How FastAPI implements DI via <code>Depends</code></p>
</li>
<li><p>Using Pydantic models as dependencies</p>
</li>
<li><p>Injecting services, config settings, database sessions</p>
</li>
<li><p>Advanced DI techniques like sub-dependencies and class-based dependencies</p>
</li>
<li><p>Best practices for clean, testable architectures</p>
</li>
</ul>
<p>Let’s get into it boss.</p>
<h2 id="heading-what-is-dependency-injection">What Is Dependency Injection?</h2>
<blockquote>
<p><strong>Dependency Injection (DI)</strong> is a design pattern where the required dependencies of a component (like a function, class, or service) are provided externally rather than being created inside the component itself.</p>
</blockquote>
<p><strong>Benefits:</strong></p>
<ul>
<li><p>Decouples modules and services</p>
</li>
<li><p>Simplifies unit testing via mock dependencies</p>
</li>
<li><p>Enhances code reusability and readability</p>
</li>
<li><p>Allows flexible configuration swapping</p>
</li>
</ul>
<h2 id="heading-dependency-injection-in-fastapi">Dependency Injection in FastAPI</h2>
<p>FastAPI uses a lightweight, intuitive DI system based on its <code>Depends</code> class.</p>
<p><strong>Basic example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Depends

app = FastAPI()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_token</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"secure-token-123"</span>

<span class="hljs-meta">@app.get("/items/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_items</span>(<span class="hljs-params">token: str = Depends(<span class="hljs-params">get_token</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"token"</span>: token}
</code></pre>
<p><strong>How it works:</strong></p>
<ul>
<li><p><code>Depends(get_token)</code> tells FastAPI to execute <code>get_token()</code> and inject the return value as the <code>token</code> parameter.</p>
</li>
<li><p>Dependencies can be synchronous or asynchronous.</p>
</li>
<li><p>Multiple dependencies can be stacked per route.</p>
</li>
</ul>
<h2 id="heading-pydantic-powered-dependency-models">Pydantic-Powered Dependency Models</h2>
<blockquote>
<p><strong>Pydantic</strong> is FastAPI’s native way to define structured, validated data. You can use Pydantic models as dependencies to enforce input schemas for injected configurations or objects.</p>
</blockquote>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>(<span class="hljs-params">BaseModel</span>):</span>
    api_key: str
    timeout: int

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_config</span>():</span>
    <span class="hljs-keyword">return</span> Config(api_key=<span class="hljs-string">"xyz-123"</span>, timeout=<span class="hljs-number">10</span>)

<span class="hljs-meta">@app.get("/settings/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_settings</span>(<span class="hljs-params">config: Config = Depends(<span class="hljs-params">get_config</span>)</span>):</span>
    <span class="hljs-keyword">return</span> config
</code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><p>Enforces type safety on injected objects</p>
</li>
<li><p>Auto-validates dependencies</p>
</li>
<li><p>Provides clear API contracts for developers</p>
</li>
</ul>
<h2 id="heading-dependency-injection-for-services">Dependency Injection for Services</h2>
<p>In scalable apps, you often need to inject <strong>services</strong> like database clients, authentication modules, or external API clients.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Database</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, url</span>):</span>
        self.url = url

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">connect</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"Connected to <span class="hljs-subst">{self.url}</span>"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_db</span>():</span>
    <span class="hljs-keyword">return</span> Database(url=<span class="hljs-string">"sqlite:///mydb.db"</span>)

<span class="hljs-meta">@app.get("/db/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">connect_to_db</span>(<span class="hljs-params">db: Database = Depends(<span class="hljs-params">get_db</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: db.connect()}
</code></pre>
<p>Now, <code>Database</code> instances are provided to each request dynamically.</p>
<h2 id="heading-dependency-overriding-test-friendly-design">Dependency Overriding (Test-Friendly Design)</h2>
<p>FastAPI allows <strong>dependency overriding</strong> at runtime — making it perfect for injecting test mocks.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">override_config</span>():</span>
    <span class="hljs-keyword">return</span> Config(api_key=<span class="hljs-string">"mock-api"</span>, timeout=<span class="hljs-number">1</span>)

app.dependency_overrides[get_config] = override_config
</code></pre>
<p>Now, all routes depending on <code>get_config()</code> will use the override — essential for isolated testing.</p>
<h2 id="heading-asynchronous-dependencies">Asynchronous Dependencies</h2>
<p>FastAPI seamlessly supports <code>async def</code> dependencies.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_data</span>():</span>
    <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">return</span> <span class="hljs-string">"async data"</span>

<span class="hljs-meta">@app.get("/data/")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_data</span>(<span class="hljs-params">data: str = Depends(<span class="hljs-params">get_data</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"data"</span>: data}
</code></pre>
<h2 id="heading-sub-dependencies-dependencies-of-dependencies">Sub-Dependencies (Dependencies of Dependencies)</h2>
<p>One dependency can depend on another, creating a <strong>dependency graph</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_username</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"vinaykumar"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_message</span>(<span class="hljs-params">username: str = Depends(<span class="hljs-params">get_username</span>)</span>):</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"Hello <span class="hljs-subst">{username}</span>"</span>

<span class="hljs-meta">@app.get("/welcome/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">welcome</span>(<span class="hljs-params">message: str = Depends(<span class="hljs-params">get_message</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: message}
</code></pre>
<p>FastAPI handles sub-dependencies automatically, resolving them in order.</p>
<h2 id="heading-class-based-dependencies">Class-Based Dependencies</h2>
<p>For complex services with state or methods, FastAPI supports <strong>classes as dependencies</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api_key: str</span>):</span>
        self.api_key = api_key

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">verify</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.api_key == <span class="hljs-string">"secure-key"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_auth</span>():</span>
    <span class="hljs-keyword">return</span> Auth(api_key=<span class="hljs-string">"secure-key"</span>)

<span class="hljs-meta">@app.get("/secure/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">secure</span>(<span class="hljs-params">auth: Auth = Depends(<span class="hljs-params">get_auth</span>)</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> auth.verify():
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"error"</span>: <span class="hljs-string">"Unauthorized"</span>}
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome Vinay"</span>}
</code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><p>Encapsulates logic cleanly</p>
</li>
<li><p>Easy to override or mock</p>
</li>
<li><p>Supports per-request state</p>
</li>
</ul>
<h2 id="heading-global-configuration-injection">Global Configuration Injection</h2>
<p>Large apps often require global config like database URLs, secrets, or environment-specific values. FastAPI encourages using <strong>Pydantic’s BaseSettings</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseSettings

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Settings</span>(<span class="hljs-params">BaseSettings</span>):</span>
    database_url: str = <span class="hljs-string">"sqlite:///prod.db"</span>
    secret_key: str = <span class="hljs-string">"secret-123"</span>

settings = Settings()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_settings</span>():</span>
    <span class="hljs-keyword">return</span> settings

<span class="hljs-meta">@app.get("/config/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">config_endpoint</span>(<span class="hljs-params">conf: Settings = Depends(<span class="hljs-params">get_settings</span>)</span>):</span>
    <span class="hljs-keyword">return</span> conf.dict()
</code></pre>
<p><strong>Advantages:</strong></p>
<ul>
<li><p>Supports <code>.env</code> files and environment variables</p>
</li>
<li><p>Centralized config management</p>
</li>
<li><p>Type-safe and validated at startup</p>
</li>
</ul>
<h2 id="heading-scoped-vs-shared-dependencies">Scoped vs Shared Dependencies</h2>
<p>By default:</p>
<ul>
<li><p><strong>Functions</strong> and <strong>classes</strong> are <strong>per-request</strong></p>
</li>
<li><p>You can force a <strong>singleton dependency</strong> (one instance reused across requests) by caching it in memory (not advised for mutable/shared state unless carefully managed)</p>
</li>
</ul>
<h2 id="heading-dependency-caching-using-dependscachetrue">Dependency Caching (Using <code>Depends(cache=True)</code>)</h2>
<p>FastAPI allows caching dependencies for a single request lifecycle.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> Request

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_unique_id</span>(<span class="hljs-params">request: Request</span>):</span>
    <span class="hljs-keyword">return</span> id(request)

<span class="hljs-meta">@app.get("/id/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">id_view</span>(<span class="hljs-params">uid: int = Depends(<span class="hljs-params">get_unique_id</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"id"</span>: uid}
</code></pre>
<p>To cache:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.get("/cached/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cached_view</span>(<span class="hljs-params">uid: int = Depends(<span class="hljs-params">get_unique_id, use_cache=True</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"cached_id"</span>: uid}
</code></pre>
<p>This prevents redundant calls to the same dependency within a single request.</p>
<h2 id="heading-dependency-injection-for-background-tasks">Dependency Injection for Background Tasks</h2>
<p><strong>BackgroundTask</strong> instances can also be injected via DI.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> BackgroundTasks

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_log</span>(<span class="hljs-params">message: str</span>):</span>
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">"log.txt"</span>, <span class="hljs-string">"a"</span>) <span class="hljs-keyword">as</span> f:
        f.write(<span class="hljs-string">f"<span class="hljs-subst">{message}</span>\n"</span>)

<span class="hljs-meta">@app.post("/notify/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">notify_user</span>(<span class="hljs-params">background_tasks: BackgroundTasks</span>):</span>
    background_tasks.add_task(write_log, <span class="hljs-string">"User Notified"</span>)
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"status"</span>: <span class="hljs-string">"Task Scheduled"</span>}
</code></pre>
<p>Clean and non-blocking.</p>
<h2 id="heading-dependency-injection-and-middleware">Dependency Injection and Middleware</h2>
<p>Dependencies can interact with middleware too — enabling powerful observability or authentication hooks.</p>
<p><strong>Example:</strong></p>
<ul>
<li><p>Dependency returns user from token</p>
</li>
<li><p>Middleware validates or logs users based on DI resolution</p>
</li>
</ul>
<p>This creates an elegant separation of concerns for cross-cutting concerns.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>FastAPI’s native <strong>Dependency Injection system</strong> is one of the most elegant and powerful features in the modern Python backend ecosystem.<br />Combined with <strong>Pydantic</strong>, it creates:</p>
<ul>
<li><p>Highly modular APIs</p>
</li>
<li><p>Clean, testable services</p>
</li>
<li><p>Decoupled configuration management</p>
</li>
<li><p>Scalable microservices architecture</p>
</li>
</ul>
<p>Whether you’re injecting a simple API key, a full-fledged ORM session, or a chain of dependent services, FastAPI’s <code>Depends</code> decorator makes it seamless.</p>
<p>By adopting these advanced DI patterns:</p>
<ul>
<li><p>You reduce coupling in your codebase</p>
</li>
<li><p>Simplify unit and integration testing</p>
</li>
<li><p>Build APIs that are clean, flexible, and future-proof</p>
</li>
</ul>
<blockquote>
<p><strong>Mastering Dependency Injection with FastAPI and Pydantic will unlock scalable, enterprise-grade application design in your Python projects.</strong></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Building Reactive Python Apps with Async Generators and Streams]]></title><description><![CDATA[Introduction

Modern applications increasingly rely on real-time data streams — from chat apps and stock tickers to IoT device feeds, real-time analytics dashboards, and webhooks. The challenge isn’t just speed, but also how to process continuous str...]]></description><link>https://blog.naveenpn.com/building-reactive-python-apps-with-async-generators-and-streams</link><guid isPermaLink="true">https://blog.naveenpn.com/building-reactive-python-apps-with-async-generators-and-streams</guid><category><![CDATA[ #AsyncGenerators ]]></category><category><![CDATA[ #PythonStreaming ]]></category><category><![CDATA[#ProducerConsumer]]></category><category><![CDATA[#ModernPython]]></category><category><![CDATA[Python]]></category><category><![CDATA[asyncio]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[websockets]]></category><category><![CDATA[realtime apps]]></category><category><![CDATA[producer consumer]]></category><category><![CDATA[ReactiveProgramming]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Fri, 20 Jun 2025 06:16:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750827515040/a3aa1f4b-f57f-43a1-a8b4-86a066db8e76.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<blockquote>
<p>Modern applications increasingly rely on <strong>real-time data streams</strong> — from chat apps and stock tickers to IoT device feeds, real-time analytics dashboards, and webhooks. The challenge isn’t just speed, but also how to process continuous streams of data efficiently, asynchronously, and non-blockingly in Python.</p>
</blockquote>
<p>While Python isn’t traditionally seen as an event-driven language like JavaScript or Elixir, recent advances with <strong>asynchronous programming</strong> (thanks to <code>asyncio</code>) and <strong>async generators</strong> have made reactive, event-driven patterns very achievable.</p>
<p>In this comprehensive guide, we’ll explore how to build <strong>reactive Python applications</strong> using:</p>
<ul>
<li><p><strong>Async generators</strong></p>
</li>
<li><p><strong>Async streams</strong></p>
</li>
<li><p><strong>Async iterators</strong></p>
</li>
<li><p><strong>Producer-consumer pipelines</strong></p>
</li>
<li><p>Modern libraries like <strong>aiohttp</strong>, <strong>asyncio streams</strong>, and <strong>FastAPI WebSockets</strong></p>
</li>
</ul>
<p>This is a fully practical, production-grade guide designed for Python developers aiming to modernize their async workflows.</p>
<h2 id="heading-what-is-reactive-programming">What Is Reactive Programming?</h2>
<blockquote>
<p><strong>Reactive programming</strong> is a declarative paradigm focused on data streams and the propagation of change. Instead of polling or synchronous request/response cycles, reactive systems <strong>react to data as it arrives</strong> — handling it asynchronously and non-blockingly.</p>
</blockquote>
<p>Use cases:</p>
<ul>
<li><p>Real-time chat applications</p>
</li>
<li><p>Live dashboards and stock tickers</p>
</li>
<li><p>Streaming file processing (CSV/JSON logs)</p>
</li>
<li><p>IoT sensor data feeds</p>
</li>
<li><p>Webhook consumers</p>
</li>
<li><p>Asynchronous pipelines</p>
</li>
</ul>
<h2 id="heading-pythons-async-foundations">Python’s Async Foundations</h2>
<p>Python introduced native <code>async</code>/<code>await</code> syntax in <strong>3.5+</strong> via the <code>asyncio</code> module, enabling asynchronous code execution using <strong>coroutines</strong> and <strong>event loops</strong>.</p>
<p>Key components:</p>
<ul>
<li><p><strong>Coroutines</strong>: Functions declared with <code>async def</code></p>
</li>
<li><p><strong>Awaitables</strong>: Objects you can <code>await</code> (including coroutines, Futures, Tasks)</p>
</li>
<li><p><strong>Event Loop</strong>: Core scheduler that runs coroutines concurrently</p>
</li>
</ul>
<p><strong>Async generators</strong> and <strong>streams</strong> were introduced in Python 3.6+, bringing reactive-like streaming to Python natively.</p>
<h2 id="heading-what-are-async-generators">What Are Async Generators?</h2>
<p>An <strong>async generator</strong> is like a regular generator but works asynchronously.</p>
<p>Syntax:</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_async_gen</span>():</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
        <span class="hljs-keyword">yield</span> i
</code></pre>
<p>But it’s designed to be consumed asynchronously:</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> my_async_gen():
    print(item)
</code></pre>
<p>It enables:</p>
<ul>
<li><p>Producing values lazily on-demand</p>
</li>
<li><p>Non-blocking operations inside the generator</p>
</li>
<li><p>Ideal for event streams, APIs, or file readers</p>
</li>
</ul>
<h2 id="heading-real-time-example-async-streaming-stock-ticker">Real-Time Example: Async Streaming Stock Ticker</h2>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">import</span> random

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stock_ticker</span>():</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        price = round(random.uniform(<span class="hljs-number">200</span>, <span class="hljs-number">500</span>), <span class="hljs-number">2</span>)
        <span class="hljs-keyword">yield</span> price
        <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_prices</span>():</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> price <span class="hljs-keyword">in</span> stock_ticker():
        print(<span class="hljs-string">f"Stock Price: ₹<span class="hljs-subst">{price}</span>"</span>)

asyncio.run(display_prices())
</code></pre>
<p><strong>Result</strong>: Live price updates every second without blocking the event loop.</p>
<h2 id="heading-async-producer-consumer-pipelines">Async Producer-Consumer Pipelines</h2>
<p>Often in reactive systems, one part of the code <strong>produces data asynchronously</strong>, while another <strong>consumes it</strong>.</p>
<p>Using an <strong>asyncio.Queue</strong>:</p>
<pre><code class="lang-python">queue = asyncio.Queue()

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">producer</span>():</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
        <span class="hljs-keyword">await</span> queue.put(<span class="hljs-string">f"Data <span class="hljs-subst">{i}</span>"</span>)
        <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">consumer</span>():</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        item = <span class="hljs-keyword">await</span> queue.get()
        print(<span class="hljs-string">f"Processed <span class="hljs-subst">{item}</span>"</span>)
        queue.task_done()

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-keyword">await</span> asyncio.gather(producer(), consumer())

asyncio.run(main())
</code></pre>
<p><strong>Features:</strong></p>
<ul>
<li><p>Non-blocking queue operations</p>
</li>
<li><p>Decouples producer and consumer</p>
</li>
<li><p>Multiple producers and consumers can be added easily</p>
</li>
</ul>
<h2 id="heading-building-async-data-streams-from-files">Building Async Data Streams from Files</h2>
<p>Reading large files line-by-line without blocking.</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_lines</span>(<span class="hljs-params">file_path</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiofiles.open(file_path, mode=<span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f:
            <span class="hljs-keyword">yield</span> line.strip()
</code></pre>
<p>Use:</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> read_lines(<span class="hljs-string">"data.txt"</span>):
    print(line)
</code></pre>
<p>This is ideal for streaming logs, CSVs, and event files.</p>
<h2 id="heading-streaming-apis-and-websockets-with-fastapi">Streaming APIs and WebSockets with FastAPI</h2>
<p><strong>FastAPI</strong> natively supports async WebSockets for reactive, real-time apps.</p>
<p>Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, WebSocket
<span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> asyncio

app = FastAPI()

<span class="hljs-meta">@app.websocket("/ws")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">websocket_endpoint</span>(<span class="hljs-params">websocket: WebSocket</span>):</span>
    <span class="hljs-keyword">await</span> websocket.accept()
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        data = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">100</span>)
        <span class="hljs-keyword">await</span> websocket.send_text(<span class="hljs-string">f"Live Value: <span class="hljs-subst">{data}</span>"</span>)
        <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)
</code></pre>
<p><strong>Run:</strong></p>
<pre><code class="lang-bash">uvicorn app:app --reload
</code></pre>
<p><strong>Usage:</strong> Open <code>ws://</code><a target="_blank" href="http://localhost:8000/ws"><code>localhost:8000/ws</code></a> via a WebSocket client.</p>
<h2 id="heading-async-streams-with-aiohttp">Async Streams with aiohttp</h2>
<p>For handling HTTP event streams or long polling:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> aiohttp
<span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_events</span>():</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiohttp.ClientSession() <span class="hljs-keyword">as</span> session:
        <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> session.get(<span class="hljs-string">"http://event-source/api/stream"</span>) <span class="hljs-keyword">as</span> resp:
            <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> resp.content:
                print(line.decode().strip())

asyncio.run(fetch_events())
</code></pre>
<p>This allows Python apps to consume real-time event streams over HTTP.</p>
<h2 id="heading-streaming-data-pipelines-with-async-generators">Streaming Data Pipelines with Async Generators</h2>
<p>Combine multiple async generators in pipelines.</p>
<p>Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">source</span>():</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
        <span class="hljs-keyword">yield</span> i
        <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">0.5</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">processor</span>(<span class="hljs-params">data_stream</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> data_stream:
        <span class="hljs-keyword">yield</span> item * <span class="hljs-number">2</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sink</span>(<span class="hljs-params">processed_stream</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> processed_stream:
        print(<span class="hljs-string">f"Processed Item: <span class="hljs-subst">{item}</span>"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pipeline</span>():</span>
    <span class="hljs-keyword">await</span> sink(processor(source()))

asyncio.run(pipeline())
</code></pre>
<p>This creates:</p>
<ul>
<li><p>A <strong>source generator</strong></p>
</li>
<li><p>A <strong>processor generator</strong></p>
</li>
<li><p>A <strong>sink consumer</strong></p>
</li>
</ul>
<p>All asynchronously chained.</p>
<h2 id="heading-async-data-filtering-with-generators">Async Data Filtering with Generators</h2>
<p>Add real-time filters.</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">filter_even</span>(<span class="hljs-params">data_stream</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> data_stream:
        <span class="hljs-keyword">if</span> item % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>:
            <span class="hljs-keyword">yield</span> item
</code></pre>
<p>Integrating:</p>
<pre><code class="lang-python"><span class="hljs-keyword">await</span> sink(filter_even(source()))
</code></pre>
<p>Now only even numbers are processed reactively.</p>
<h2 id="heading-error-handling-in-async-streams">Error Handling in Async Streams</h2>
<p>Use <code>try-except</code> inside async generators to handle stream errors.</p>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">safe_processor</span>(<span class="hljs-params">data_stream</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> data_stream:
        <span class="hljs-keyword">try</span>:
            <span class="hljs-keyword">if</span> item == <span class="hljs-number">5</span>:
                <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Bad value!"</span>)
            <span class="hljs-keyword">yield</span> item
        <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
            print(<span class="hljs-string">f"Error: <span class="hljs-subst">{e}</span>"</span>)
</code></pre>
<p>Ensures stream resilience without stopping the pipeline.</p>
<h2 id="heading-performance-tips-for-async-streams">Performance Tips for Async Streams</h2>
<ul>
<li><p>Use <strong>bounded queues</strong> to prevent memory bloat in high-frequency streams</p>
</li>
<li><p>Always <strong>await sleep or IO</strong> operations in async generators</p>
</li>
<li><p>Use <code>asyncio.gather()</code> for running multiple producers/consumers concurrently</p>
</li>
<li><p>Implement <strong>backpressure</strong> with <code>Queue.maxsize</code> and blocking <code>put</code></p>
</li>
<li><p>Profile async apps with <strong>aiomonitor</strong> or <strong>Py-Spy</strong></p>
</li>
</ul>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<p><strong>Chat Application</strong></p>
<ul>
<li><p>User messages streamed via WebSockets</p>
</li>
<li><p>Async generator yields new messages to connected clients</p>
</li>
</ul>
<p><strong>IoT Data Aggregator</strong></p>
<ul>
<li><p>Devices stream data points over HTTP</p>
</li>
<li><p>Async producer-consumer queues aggregate and process data</p>
</li>
</ul>
<p><strong>Log File Watcher</strong></p>
<ul>
<li><p>Tails server logs using async file streams</p>
</li>
<li><p>Triggers alerts on error patterns in real-time</p>
</li>
</ul>
<p><strong>Streaming API Gateway</strong></p>
<ul>
<li><p>Consumes external API data via async HTTP</p>
</li>
<li><p>Transforms and forwards events downstream without blocking</p>
</li>
</ul>
<h2 id="heading-modern-libraries-supporting-async-streams">Modern Libraries Supporting Async Streams</h2>
<ul>
<li><p><strong>aiohttp</strong>: Async HTTP client and server</p>
</li>
<li><p><strong>aiofiles</strong>: Async file operations</p>
</li>
<li><p><strong>aiomonitor</strong>: Real-time asyncio event loop introspection</p>
</li>
<li><p><strong>FastAPI</strong>: Async WebSockets and HTTP streaming</p>
</li>
<li><p><strong>aiostream</strong>: Higher-level async stream processing utilities</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> aiostream.stream

stream = aiostream.stream.repeat(<span class="hljs-number">42</span>, count=<span class="hljs-number">10</span>)
<span class="hljs-keyword">async</span> <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> stream:
    print(item)
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Reactive, event-driven architectures are the future of modern Python applications. Thanks to <code>asyncio</code>, <strong>async generators</strong>, and streaming protocols like WebSockets, Python has become a capable, reliable platform for building real-time, non-blocking systems.</p>
<p>Key takeaways:</p>
<ul>
<li><p>Use <strong>async generators</strong> to lazily produce data</p>
</li>
<li><p>Build <strong>producer-consumer pipelines</strong> using <code>asyncio.Queue</code></p>
</li>
<li><p>Consume real-time <strong>WebSockets and HTTP event streams</strong></p>
</li>
<li><p>Chain multiple async data processors for clean, reactive pipelines</p>
</li>
<li><p>Manage errors, backpressure, and timeouts for resilient streaming systems</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Zero-Downtime Deployments in Python with Uvicorn, Gunicorn, and Async FastAPI APIs]]></title><description><![CDATA[Introduction

Modern applications need to stay online, responsive, and resilient even during upgrades, deployments, or infrastructure changes. Users today expect 24/7 availability — downtime is no longer acceptable for APIs, web services, or internal...]]></description><link>https://blog.naveenpn.com/zero-downtime-deployments-in-python-with-uvicorn-gunicorn-and-async-fastapi-apis</link><guid isPermaLink="true">https://blog.naveenpn.com/zero-downtime-deployments-in-python-with-uvicorn-gunicorn-and-async-fastapi-apis</guid><category><![CDATA[Python]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[#unicorn]]></category><category><![CDATA[Gunicorn]]></category><category><![CDATA[Zero Downtime]]></category><category><![CDATA[Devops]]></category><category><![CDATA[asyncio]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[cloud deployment]]></category><category><![CDATA[appdeployment]]></category><category><![CDATA[ScalableInfrastructure ]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Fri, 20 Jun 2025 05:45:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750827651752/6e44496b-7a11-462f-ad17-859360d9ba8e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<blockquote>
<p>Modern applications need to stay online, responsive, and resilient even during upgrades, deployments, or infrastructure changes. Users today expect 24/7 availability — downtime is no longer acceptable for APIs, web services, or internal systems.</p>
<p>In Python-based backend architectures, particularly those built on <strong>FastAPI</strong> or other async frameworks like <strong>Starlette</strong> or <strong>Sanic</strong>, achieving <strong>zero-downtime deployments</strong> is both essential and achievable with the right tools and deployment patterns.</p>
</blockquote>
<p>This guide will give you a practical, production-ready strategy for zero-downtime deployments using:</p>
<ul>
<li><p><strong>Uvicorn</strong>: a lightning-fast ASGI server</p>
</li>
<li><p><strong>Gunicorn</strong>: a battle-tested WSGI/ASGI process manager</p>
</li>
<li><p><strong>Systemd, Supervisor, or Docker</strong> for process management</p>
</li>
<li><p>Techniques like <strong>graceful restarts</strong>, <strong>blue-green deployments</strong>, and <strong>load balancer draining</strong></p>
</li>
</ul>
<p>Let’s get into it, boss.</p>
<h2 id="heading-why-zero-downtime-deployments-matter">Why Zero-Downtime Deployments Matter</h2>
<p>Downtime during deployments affects:</p>
<ul>
<li><p>API consumers (mobile apps, frontends)</p>
</li>
<li><p>Automated services (cron jobs, integrations)</p>
</li>
<li><p>Transactional operations (payment gateways, notifications)</p>
</li>
<li><p>User trust and SLAs</p>
</li>
</ul>
<p>Modern best practices expect:</p>
<ul>
<li><p><strong>New code goes live without stopping existing traffic</strong></p>
</li>
<li><p><strong>In-flight requests complete without being killed</strong></p>
</li>
<li><p><strong>New processes gradually replace old ones</strong></p>
</li>
</ul>
<p>This applies to cloud-native apps, containerized services, and monolithic APIs alike.</p>
<h2 id="heading-fastapi-uvicorn-and-gunicorn-how-they-fit-together">FastAPI, Uvicorn, and Gunicorn — How They Fit Together</h2>
<blockquote>
<p><strong>FastAPI</strong> is an asynchronous Python web framework built on <strong>Starlette</strong>.</p>
<p><strong>Uvicorn</strong> is an ASGI server that runs async apps efficiently.</p>
<p><strong>Gunicorn</strong> is a WSGI/ASGI HTTP server capable of managing multiple Uvicorn worker processes, handling process management, graceful shutdowns, and zero-downtime reloads.</p>
</blockquote>
<p><strong>Together:</strong></p>
<ul>
<li><p>FastAPI handles API routes and logic</p>
</li>
<li><p>Uvicorn serves FastAPI with event loops and ASGI support</p>
</li>
<li><p>Gunicorn supervises and manages Uvicorn workers</p>
</li>
</ul>
<h2 id="heading-installing-the-stack">Installing the Stack</h2>
<p>First, install the essentials:</p>
<pre><code class="lang-bash">pip install fastapi uvicorn gunicorn
</code></pre>
<p>Test run:</p>
<pre><code class="lang-bash">uvicorn app:app --reload
</code></pre>
<h2 id="heading-why-gunicorn-uvicorn-for-production">Why Gunicorn + Uvicorn for Production</h2>
<ul>
<li><p><strong>Uvicorn</strong> alone is ideal for development or simple production apps</p>
</li>
<li><p><strong>Gunicorn</strong> adds:</p>
<ul>
<li><p>Multiple Uvicorn workers</p>
</li>
<li><p>Graceful reloads (<code>HUP</code> signal handling)</p>
</li>
<li><p>Worker timeouts, limits, hooks</p>
</li>
<li><p>Load balancing across CPUs</p>
</li>
<li><p>Better logging and process supervision</p>
</li>
</ul>
</li>
</ul>
<p><strong>FastAPI officially recommends Uvicorn + Gunicorn for production</strong></p>
<h2 id="heading-basic-gunicorn-uvicorn-command">Basic Gunicorn + Uvicorn Command</h2>
<p>Basic production command:</p>
<pre><code class="lang-bash">gunicorn app:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --<span class="hljs-built_in">bind</span> 0.0.0.0:8000
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><p><code>--workers 4</code>: Number of worker processes (adjust to CPU cores)</p>
</li>
<li><p><code>--worker-class uvicorn.workers.UvicornWorker</code>: ASGI-compatible worker</p>
</li>
<li><p><code>--bind</code>: Host and port</p>
</li>
</ul>
<h2 id="heading-graceful-restart-zero-downtime-technique-1">Graceful Restart: Zero Downtime Technique 1</h2>
<blockquote>
<p><strong>Graceful restarts</strong> allow you to reload code without killing existing in-flight connections. Gunicorn supports this natively.</p>
</blockquote>
<p>To gracefully reload:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">kill</span> -HUP &lt;master-pid&gt;
</code></pre>
<p><strong>What happens:</strong></p>
<ul>
<li><p>Gunicorn forks new Uvicorn workers</p>
</li>
<li><p>Old workers finish active requests</p>
</li>
<li><p>Old workers terminate only after completing current tasks</p>
</li>
<li><p>New workers take over</p>
</li>
</ul>
<p><strong>Get Gunicorn master PID:</strong></p>
<pre><code class="lang-bash">ps aux | grep gunicorn
</code></pre>
<p>This strategy alone can achieve zero downtime for most Python APIs.</p>
<h2 id="heading-configuration-example-gunicorn-config-file">Configuration Example: Gunicorn Config File</h2>
<p>Create <code>gunicorn_</code><a target="_blank" href="http://conf.py"><code>conf.py</code></a></p>
<pre><code class="lang-python">bind = <span class="hljs-string">"0.0.0.0:8000"</span>
workers = <span class="hljs-number">4</span>
worker_class = <span class="hljs-string">"uvicorn.workers.UvicornWorker"</span>
timeout = <span class="hljs-number">30</span>
graceful_timeout = <span class="hljs-number">10</span>
keepalive = <span class="hljs-number">5</span>
</code></pre>
<p>Run it:</p>
<pre><code class="lang-bash">gunicorn app:app -c gunicorn_conf.py
</code></pre>
<p><strong>Benefits:</strong></p>
<ul>
<li><p>Clean separation of deployment configs</p>
</li>
<li><p>Easy to adjust concurrency and timeouts</p>
</li>
<li><p>Avoids command-line complexity</p>
</li>
</ul>
<h2 id="heading-zero-downtime-deployment-strategy-2-blue-green-deployments">Zero-Downtime Deployment Strategy 2: Blue-Green Deployments</h2>
<p><strong>Blue-green deployment</strong> keeps two identical environments:</p>
<ul>
<li><p><strong>Blue</strong>: Current live production environment</p>
</li>
<li><p><strong>Green</strong>: New version to deploy</p>
</li>
</ul>
<p><strong>How it works:</strong></p>
<ol>
<li><p>Deploy new FastAPI app version to Green (new port or server)</p>
</li>
<li><p>Health-check it independently</p>
</li>
<li><p>Switch load balancer routing from Blue to Green</p>
</li>
<li><p>Shut down Blue only after Green is fully live</p>
</li>
</ol>
<p><strong>Advantages:</strong></p>
<ul>
<li><p>Instant rollback possible</p>
</li>
<li><p>No downtime perceived by clients</p>
</li>
<li><p>Seamless version transitions</p>
</li>
</ul>
<p><strong>Implementation:</strong></p>
<ul>
<li><p>Use Nginx, HAProxy, AWS ALB, or cloud load balancer</p>
</li>
<li><p>Point backend pool to new Gunicorn+Uvicorn instance gradually</p>
</li>
</ul>
<h2 id="heading-deployment-strategy-3-rolling-updates-with-load-balancer-draining">Deployment Strategy 3: Rolling Updates with Load Balancer Draining</h2>
<p>In containerized or multi-node setups:</p>
<ol>
<li><p>Set app container or server to "drain mode"</p>
</li>
<li><p>Stop sending new requests to instance</p>
</li>
<li><p>Wait for in-flight requests to finish</p>
</li>
<li><p>Restart or update instance</p>
</li>
<li><p>Put instance back into rotation</p>
</li>
</ol>
<p><strong>Most cloud load balancers (AWS ALB, Azure Front Door, GCP LB)</strong> and Nginx upstreams support draining.</p>
<h2 id="heading-process-management-in-production">Process Management in Production</h2>
<p><strong>Systemd Unit Example</strong></p>
<p>Create <code>/etc/systemd/system/myapp.service</code></p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=Gunicorn instance for FastAPI app
<span class="hljs-attr">After</span>=network.target

<span class="hljs-section">[Service]</span>
<span class="hljs-attr">User</span>=ubuntu
<span class="hljs-attr">Group</span>=www-data
<span class="hljs-attr">WorkingDirectory</span>=/home/ubuntu/myapp
<span class="hljs-attr">ExecStart</span>=/home/ubuntu/.venv/bin/gunicorn -c /home/ubuntu/myapp/gunicorn_conf.py app:app

<span class="hljs-section">[Install]</span>
<span class="hljs-attr">WantedBy</span>=multi-user.target
</code></pre>
<p><strong>Start / Stop / Restart</strong></p>
<pre><code class="lang-bash">sudo systemctl start myapp
sudo systemctl restart myapp
sudo systemctl <span class="hljs-built_in">enable</span> myapp
</code></pre>
<p><strong>Supports graceful reload via:</strong></p>
<pre><code class="lang-bash">sudo systemctl reload myapp
</code></pre>
<p><strong>Or via HUP signal</strong></p>
<h2 id="heading-monitoring-and-health-checks">Monitoring and Health Checks</h2>
<p>Important for reliable zero-downtime deployments:</p>
<ul>
<li><p>FastAPI: implement <code>/health</code> or <code>/ready</code> endpoints</p>
</li>
<li><p>Gunicorn: monitor logs and worker stats</p>
</li>
<li><p>Load Balancer: configure health check URL</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI

app = FastAPI()

<span class="hljs-meta">@app.get("/health")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">health_check</span>():</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"status"</span>: <span class="hljs-string">"ok"</span>}
</code></pre>
<h2 id="heading-dockerized-zero-downtime-deployments">Dockerized Zero-Downtime Deployments</h2>
<p><strong>Docker Compose Example</strong></p>
<p><code>docker-compose.yml</code></p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>

<span class="hljs-attr">services:</span>
  <span class="hljs-attr">app:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">.</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">gunicorn</span> <span class="hljs-string">-c</span> <span class="hljs-string">gunicorn_conf.py</span> <span class="hljs-string">app:app</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8000:8000"</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">always</span>
</code></pre>
<p><strong>Rolling deployment workflow:</strong></p>
<ol>
<li><p>Build new image version</p>
</li>
<li><p>Use <code>docker-compose up -d --scale app=2</code> to double instances</p>
</li>
<li><p>Health-check new container</p>
</li>
<li><p>Remove old container</p>
</li>
<li><p>Repeat</p>
</li>
</ol>
<p><strong>Kubernetes equivalent: RollingUpdate strategy in Deployment spec</strong></p>
<h2 id="heading-fastapi-uvicorn-gunicorn-performance-tuning-tips">FastAPI Uvicorn Gunicorn Performance Tuning Tips</h2>
<ul>
<li><p>Match <code>--workers</code> to (2 × CPU cores) + 1 rule of thumb</p>
</li>
<li><p>Use <code>--keep-alive</code> for persistent connections</p>
</li>
<li><p>Set appropriate <code>timeout</code> for slow upstream calls</p>
</li>
<li><p>Profile with <code>wrk</code>, <code>ab</code>, or <code>hey</code> for bottlenecks</p>
</li>
<li><p>Use ASGI lifespan events (<code>on_startup</code> / <code>on_shutdown</code>) for clean worker management</p>
</li>
</ul>
<h2 id="heading-common-deployment-mistakes-to-avoid">Common Deployment Mistakes to Avoid</h2>
<ul>
<li><p>Forgetting to drain old workers before deploying</p>
</li>
<li><p>Not setting <code>graceful_timeout</code> causing abrupt kills</p>
</li>
<li><p>Overloading <code>--workers</code> leading to OOM kills</p>
</li>
<li><p>Omitting load balancer health checks, causing downtime during rollout</p>
</li>
<li><p>Not separating staging and production environments</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Zero-downtime deployments are crucial for maintaining API availability, user experience, and system reliability in modern infrastructure.</p>
<p>With a combination of:</p>
<ul>
<li><p><strong>FastAPI</strong> async power</p>
</li>
<li><p><strong>Uvicorn</strong>’s high-performance ASGI server</p>
</li>
<li><p><strong>Gunicorn</strong>’s reliable process management and graceful restarts</p>
</li>
<li><p>Deployment strategies like <strong>graceful reloads</strong>, <strong>blue-green rollouts</strong>, and <strong>rolling updates</strong></p>
</li>
<li><p>And proper <strong>load balancer health checks</strong></p>
</li>
</ul>
<p>You can confidently deploy new versions of your Python applications without dropping a single request.</p>
]]></content:encoded></item><item><title><![CDATA[Implementing Task Queues in Python Using Celery and Redis — Scalable Background Jobs]]></title><description><![CDATA[Introduction

In the world of modern applications — APIs, web services, machine learning pipelines, IoT, and enterprise systems — it’s common to encounter tasks that shouldn’t or can’t be processed immediately within a request-response cycle. These i...]]></description><link>https://blog.naveenpn.com/implementing-task-queues-in-python-using-celery-and-redis-scalable-background-jobs</link><guid isPermaLink="true">https://blog.naveenpn.com/implementing-task-queues-in-python-using-celery-and-redis-scalable-background-jobs</guid><category><![CDATA[ #TaskQueue ]]></category><category><![CDATA[#PythonBackend ]]></category><category><![CDATA[celery]]></category><category><![CDATA[Redis]]></category><category><![CDATA[background jobs]]></category><category><![CDATA[asynchronous programming]]></category><category><![CDATA[ScalableApps]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[distributed systems]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Fri, 20 Jun 2025 05:37:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752850580442/82ae54f6-01c9-4bc8-8ade-d33609042852.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<blockquote>
<p>In the world of modern applications — APIs, web services, machine learning pipelines, IoT, and enterprise systems — it’s common to encounter tasks that shouldn’t or can’t be processed immediately within a request-response cycle. These include sending emails, resizing images, generating reports, making API calls, or training models.</p>
</blockquote>
<p>Trying to perform these actions synchronously results in slow APIs, degraded UX, and inefficient resource usage. The ideal solution is to process these time-consuming operations <strong>asynchronously in the background</strong> using a <strong>task queue</strong> system.</p>
<blockquote>
<p><strong>Celery</strong> is one of Python’s most robust, mature, and production-grade libraries for managing asynchronous tasks and distributed job queues. Combined with a message broker like <strong>Redis</strong>, it can handle millions of background tasks efficiently.</p>
</blockquote>
<p>This comprehensive guide covers:</p>
<ul>
<li><p>Why you need task queues</p>
</li>
<li><p>How Celery works under the hood</p>
</li>
<li><p>Setting up Redis as a broker</p>
</li>
<li><p>Writing and queuing background jobs</p>
</li>
<li><p>Running Celery workers and monitoring queues</p>
</li>
<li><p>Handling task retries, results, and periodic scheduling</p>
</li>
<li><p>Deployment strategies for production-ready setups</p>
</li>
</ul>
<h2 id="heading-why-you-need-task-queues">Why You Need Task Queues</h2>
<p>Modern applications need to perform certain operations asynchronously, outside the primary execution thread. Task queues enable:</p>
<ul>
<li><p><strong>Decoupling of long-running jobs</strong> from user-facing services</p>
</li>
<li><p><strong>Retrying failed tasks</strong> automatically</p>
</li>
<li><p><strong>Distributing load</strong> across multiple workers and machines</p>
</li>
<li><p><strong>Scaling background job processing</strong> without affecting the core application</p>
</li>
</ul>
<p>Common use cases:</p>
<ul>
<li><p>Sending emails and SMS</p>
</li>
<li><p>Resizing images and videos</p>
</li>
<li><p>Processing uploads and downloads</p>
</li>
<li><p>Running scheduled jobs (CRON-like tasks)</p>
</li>
<li><p>Interacting with third-party services (payment gateways, APIs)</p>
</li>
<li><p>Training ML models and data ETL pipelines</p>
</li>
</ul>
<h2 id="heading-what-is-celery">What is Celery?</h2>
<blockquote>
<p><strong>Celery</strong> is an open-source, distributed task queue library written in Python. It uses a <strong>message broker</strong> (like Redis, RabbitMQ) to send and receive task messages. Celery workers listen to these queues, pick up tasks, and execute them asynchronously.</p>
</blockquote>
<p>Key features:</p>
<ul>
<li><p>Supports multiple brokers: Redis, RabbitMQ, Amazon SQS</p>
</li>
<li><p>Highly scalable — can run on a single node or across distributed servers</p>
</li>
<li><p>Provides task retrying, time limits, rate limits, and priority queues</p>
</li>
<li><p>Built-in result backend for tracking task status and results</p>
</li>
<li><p>Native periodic task scheduling (beat scheduler)</p>
</li>
<li><p>Integrates well with Django, Flask, FastAPI, and standalone Python scripts</p>
</li>
</ul>
<h2 id="heading-how-celery-works">How Celery Works</h2>
<p>Celery’s architecture involves four main components:</p>
<ol>
<li><p><strong>Producer (Application/API):</strong> Places tasks into a queue.</p>
</li>
<li><p><strong>Broker (Redis):</strong> Acts as a message queue to deliver tasks to workers.</p>
</li>
<li><p><strong>Worker:</strong> Executes tasks asynchronously from the queue.</p>
</li>
<li><p><strong>Result Backend (optional):</strong> Stores task execution results for later retrieval.</p>
</li>
</ol>
<p>When a task is called asynchronously, Celery serializes the task information (function name, arguments) and sends it to the broker. A worker process picks up the message, executes the function, and optionally stores the result.</p>
<h2 id="heading-setting-up-redis-as-a-broker">Setting Up Redis as a Broker</h2>
<p>First, install Redis locally or use a cloud-managed service.</p>
<p>On Ubuntu:</p>
<pre><code class="lang-bash">sudo apt-get install redis-server
sudo systemctl <span class="hljs-built_in">enable</span> redis
sudo systemctl start redis
</code></pre>
<p>Test Redis:</p>
<pre><code class="lang-bash">redis-cli ping
</code></pre>
<p>It should return:</p>
<pre><code class="lang-plaintext">PONG
</code></pre>
<h2 id="heading-installing-celery">Installing Celery</h2>
<p>Install Celery and the Redis client:</p>
<pre><code class="lang-bash">pip install celery redis
</code></pre>
<h2 id="heading-creating-a-basic-celery-app">Creating a Basic Celery App</h2>
<p>Create a new Python file called <a target="_blank" href="http://tasks.py"><code>tasks.py</code></a>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery <span class="hljs-keyword">import</span> Celery

app = Celery(
    <span class="hljs-string">'background_tasks'</span>,
    broker=<span class="hljs-string">'redis://localhost:6379/0'</span>,
    backend=<span class="hljs-string">'redis://localhost:6379/1'</span>
)

<span class="hljs-meta">@app.task</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x + y
</code></pre>
<p>Explanation:</p>
<ul>
<li><p><code>broker</code> tells Celery where to send and fetch task messages.</p>
</li>
<li><p><code>backend</code> stores the task result and status.</p>
</li>
<li><p>The <code>@app.task</code> decorator registers a function as a Celery task.</p>
</li>
</ul>
<h2 id="heading-running-celery-workers">Running Celery Workers</h2>
<p>Open a new terminal window and start a Celery worker:</p>
<pre><code class="lang-bash">celery -A tasks worker --loglevel=info
</code></pre>
<p><strong>Options:</strong></p>
<ul>
<li><p><code>-A tasks</code> refers to the file (without <code>.py</code>) where the Celery app is defined.</p>
</li>
<li><p><code>--loglevel=info</code> outputs real-time logs.</p>
</li>
</ul>
<p>You’ll see:</p>
<pre><code class="lang-plaintext">[tasks]
  . tasks.add
</code></pre>
<p>The worker is now ready to process tasks.</p>
<h2 id="heading-sending-tasks-asynchronously">Sending Tasks Asynchronously</h2>
<p>Now, in a Python shell or separate script:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> tasks <span class="hljs-keyword">import</span> add

result = add.delay(<span class="hljs-number">5</span>, <span class="hljs-number">7</span>)
print(result.id)
</code></pre>
<p><code>add.delay(5, 7)</code> queues the task asynchronously.</p>
<p>Check the task status:</p>
<pre><code class="lang-python">result.status
</code></pre>
<p>Retrieve the result:</p>
<pre><code class="lang-python">result.get(timeout=<span class="hljs-number">10</span>)
</code></pre>
<h2 id="heading-retrying-failed-tasks">Retrying Failed Tasks</h2>
<p>Celery can automatically retry failed tasks.</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.task(bind=True, max_retries=3)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">risky_operation</span>(<span class="hljs-params">self, x</span>):</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">if</span> x == <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Invalid value"</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-number">10</span> / x
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> exc:
        <span class="hljs-keyword">raise</span> self.retry(exc=exc, countdown=<span class="hljs-number">5</span>)
</code></pre>
<p><strong>Parameters:</strong></p>
<ul>
<li><p><code>bind=True</code> gives the task access to itself.</p>
</li>
<li><p><code>max_retries</code> limits retry attempts.</p>
</li>
<li><p><code>countdown</code> adds a delay before retrying.</p>
</li>
</ul>
<h2 id="heading-task-time-limits-and-rate-limits">Task Time Limits and Rate Limits</h2>
<p>To prevent runaway tasks:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.task(time_limit=30, rate_limit='10/m')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">heavy_task</span>():</span>
    <span class="hljs-comment"># Expensive operation</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><p><code>time_limit=30</code> enforces a 30-second max runtime.</p>
</li>
<li><p><code>rate_limit='10/m'</code> limits to 10 executions per minute.</p>
</li>
</ul>
<h2 id="heading-result-backend-and-storing-task-results">Result Backend and Storing Task Results</h2>
<p>The result backend can store the outcome and status of tasks. Redis works well for this.</p>
<p>Retrieving results:</p>
<pre><code class="lang-python">result = add.delay(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>)
print(result.get(timeout=<span class="hljs-number">5</span>))
</code></pre>
<p>You can query task status:</p>
<pre><code class="lang-python">print(result.ready())   <span class="hljs-comment"># True or False</span>
print(result.successful())
</code></pre>
<p><strong>Alternative backends:</strong> RabbitMQ, MySQL, PostgreSQL, Amazon S3, Memcached.</p>
<h2 id="heading-periodic-task-scheduling">Periodic Task Scheduling</h2>
<p>Use <strong>Celery Beat</strong>, a scheduler service that kicks off tasks at regular intervals.</p>
<p>Install:</p>
<pre><code class="lang-bash">pip install django-celery-beat
</code></pre>
<p>Create a scheduler config:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery.schedules <span class="hljs-keyword">import</span> crontab

app.conf.beat_schedule = {
    <span class="hljs-string">'send-reminder-every-minute'</span>: {
        <span class="hljs-string">'task'</span>: <span class="hljs-string">'tasks.send_reminder'</span>,
        <span class="hljs-string">'schedule'</span>: crontab(minute=<span class="hljs-string">'*'</span>),
    },
}
</code></pre>
<p>Run the scheduler:</p>
<pre><code class="lang-bash">celery -A tasks beat --loglevel=info
</code></pre>
<p>Now <code>send_reminder</code> runs every minute.</p>
<h2 id="heading-chaining-and-grouping-tasks">Chaining and Grouping Tasks</h2>
<p>Celery supports complex workflows.</p>
<p><strong>Task Chaining</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery <span class="hljs-keyword">import</span> chain

chain(add.s(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>) | add.s(<span class="hljs-number">10</span>))()
</code></pre>
<p>Result: <code>(4+6)=10</code>, then <code>10+10=20</code></p>
<p><strong>Parallel Execution (Groups)</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery <span class="hljs-keyword">import</span> group

group(add.s(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>), add.s(<span class="hljs-number">3</span>, <span class="hljs-number">3</span>))().get()
</code></pre>
<h2 id="heading-deployment-strategies">Deployment Strategies</h2>
<p>In production:</p>
<ul>
<li><p>Use <strong>supervisord</strong>, <strong>systemd</strong>, or <strong>Docker</strong> to manage Celery worker processes.</p>
</li>
<li><p>Run multiple worker instances across machines.</p>
</li>
<li><p>Use <strong>Redis Sentinel</strong> or <strong>Amazon ElastiCache</strong> for highly available Redis brokers.</p>
</li>
<li><p>Monitor queues with tools like <strong>Flower</strong> (<code>pip install flower</code>).</p>
</li>
</ul>
<p>Launch Flower:</p>
<pre><code class="lang-bash">celery -A tasks flower
</code></pre>
<p>Access it at <a target="_blank" href="http://localhost:5555"><code>http://localhost:5555</code></a></p>
<h2 id="heading-performance-tips">Performance Tips</h2>
<ul>
<li><p>Always set a <code>time_limit</code> on long-running tasks.</p>
</li>
<li><p>Avoid storing large payloads in Redis result backend.</p>
</li>
<li><p>Use task routing and named queues for load balancing.</p>
</li>
<li><p>Disable result storage for fire-and-forget tasks.</p>
</li>
<li><p>Compress messages with <code>app.conf.task_compression = 'gzip'</code></p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Asynchronous background processing is indispensable in modern application development. Python’s Celery, paired with Redis, offers a scalable, reliable, and feature-rich solution for handling distributed task queues.</p>
<p>This guide covered:</p>
<ul>
<li><p>Celery’s architecture</p>
</li>
<li><p>Task creation and asynchronous execution</p>
</li>
<li><p>Worker management and scheduling</p>
</li>
<li><p>Task retries, chaining, and result storage</p>
</li>
<li><p>Production deployment and performance optimization</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Python’s structlog: Modern Structured Logging for Clean, JSON-Ready Logs]]></title><description><![CDATA[Introduction

Logging is one of the most overlooked yet critical aspects of building reliable and scalable applications. In traditional Python applications, developers commonly rely on the built-in logging module, sprinkling simple log messages like ...]]></description><link>https://blog.naveenpn.com/pythons-structlog-modern-structured-logging-for-clean-json-ready-logs</link><guid isPermaLink="true">https://blog.naveenpn.com/pythons-structlog-modern-structured-logging-for-clean-json-ready-logs</guid><category><![CDATA[ #StructuredLogging ]]></category><category><![CDATA[#Structlog]]></category><category><![CDATA[ #JSONLogs ]]></category><category><![CDATA[ #PythonDev ]]></category><category><![CDATA[Python]]></category><category><![CDATA[python-logging]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[observability]]></category><category><![CDATA[cloud native]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Fri, 20 Jun 2025 05:24:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752850916227/e21cc71c-e3da-4356-a53b-0c7a152a4985.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<blockquote>
<p>Logging is one of the most overlooked yet critical aspects of building reliable and scalable applications. In traditional Python applications, developers commonly rely on the built-in <code>logging</code> module, sprinkling simple log messages like <code>print()</code> or <a target="_blank" href="http://logger.info"><code>logger.info</code></a><code>()</code> throughout their code.</p>
</blockquote>
<p>However, as systems become distributed, containerized, cloud-native, or integrated into microservices, <strong>structured logging</strong> has become a necessity. Structured logs — logs with machine-readable key-value data instead of plain text — allow powerful querying, filtering, and visualization in modern observability tools like ELK (Elasticsearch-Logstash-Kibana), Loki, Datadog, and AWS CloudWatch.</p>
<p>This is where <code>structlog</code> comes in. It’s a modern, high-performance Python library for <strong>structured logging</strong> that integrates cleanly with the existing <code>logging</code> module but transforms your logs into JSON-ready, structured messages.</p>
<p>This article offers a deep dive into <code>structlog</code>, covering:</p>
<ul>
<li><p>Why structured logging matters</p>
</li>
<li><p>How <code>structlog</code> works under the hood</p>
</li>
<li><p>Integrating it with Python’s <code>logging</code></p>
</li>
<li><p>Custom processors and contextual logging</p>
</li>
<li><p>JSON logs for modern deployments</p>
</li>
<li><p>Performance considerations</p>
</li>
<li><p>Production-ready logging setups with <code>structlog</code></p>
</li>
</ul>
<h2 id="heading-why-structured-logging">Why Structured Logging?</h2>
<blockquote>
<p>In traditional applications, logs look like this:</p>
</blockquote>
<pre><code class="lang-plaintext">[INFO] User Vinay logged in from IP 192.168.1.1
</code></pre>
<blockquote>
<p>In modern, distributed systems, this is insufficient. Instead, you'd want:</p>
</blockquote>
<pre><code class="lang-json">{
  <span class="hljs-attr">"level"</span>: <span class="hljs-string">"info"</span>,
  <span class="hljs-attr">"event"</span>: <span class="hljs-string">"user_logged_in"</span>,
  <span class="hljs-attr">"user"</span>: <span class="hljs-string">"Vinay"</span>,
  <span class="hljs-attr">"ip"</span>: <span class="hljs-string">"192.168.1.1"</span>,
  <span class="hljs-attr">"timestamp"</span>: <span class="hljs-string">"2025-06-20T08:00:00Z"</span>
}
</code></pre>
<p><strong>Advantages:</strong></p>
<ul>
<li><p>Easily query logs by fields (user, IP, timestamp)</p>
</li>
<li><p>Structured, consistent logs for dashboards</p>
</li>
<li><p>Machine-readable (JSON/YAML/Key-Value pairs)</p>
</li>
<li><p>Better correlation in distributed tracing</p>
</li>
<li><p>Simplifies debugging, alerting, and anomaly detection</p>
</li>
</ul>
<h2 id="heading-what-is-structlog">What is <code>structlog</code>?</h2>
<blockquote>
<p><code>structlog</code> is a Python logging library designed for structured logging.</p>
</blockquote>
<p><strong>Key features:</strong></p>
<ul>
<li><p>Lightweight and fast</p>
</li>
<li><p>Integrates with <code>logging</code> or works independently</p>
</li>
<li><p>Supports context-aware, thread-safe logging</p>
</li>
<li><p>Serializes logs into JSON or custom formats</p>
</li>
<li><p>Pluggable processor pipeline to enrich or transform log events</p>
</li>
<li><p>Production-ready for microservices and cloud apps</p>
</li>
</ul>
<h2 id="heading-installing-structlog">Installing <code>structlog</code></h2>
<p>Install using pip:</p>
<pre><code class="lang-bash">pip install structlog
</code></pre>
<p>For JSON logging:</p>
<pre><code class="lang-bash">pip install structlog[json]
</code></pre>
<h2 id="heading-basic-usage">Basic Usage</h2>
<p>A simple example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> structlog

log = structlog.get_logger()
log.info(<span class="hljs-string">"user_logged_in"</span>, user=<span class="hljs-string">"Vinay"</span>, ip=<span class="hljs-string">"192.168.1.1"</span>)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">2025-06-20 08:00.00 [info     ] user_logged_in          user=Vinay ip=192.168.1.1
</code></pre>
<p>This is human-readable, but you can swap the processor chain to output JSON as well.</p>
<h2 id="heading-how-structlog-works">How <code>structlog</code> Works</h2>
<p>At its core, <code>structlog</code> separates concerns:</p>
<ul>
<li><p><strong>Logger binding:</strong> Attach context (key-value data) to logger instances</p>
</li>
<li><p><strong>Event processors:</strong> Modify, filter, or enrich log events</p>
</li>
<li><p><strong>Renderer:</strong> Transform the final log event into a string or JSON before emitting it</p>
</li>
</ul>
<p>This pipeline design makes it extremely flexible.</p>
<h2 id="heading-integrating-structlog-with-pythons-logging-module">Integrating <code>structlog</code> with Python’s <code>logging</code> Module</h2>
<p>To capture logs from third-party libraries or use existing handlers like <code>RotatingFileHandler</code>, integrate with <code>logging</code>.</p>
<p>Example setup:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">import</span> structlog

logging.basicConfig(
    format=<span class="hljs-string">"%(message)s"</span>,
    stream=sys.stdout,
    level=logging.INFO
)

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt=<span class="hljs-string">"iso"</span>),
        structlog.processors.add_log_level,
        structlog.processors.KeyValueRenderer(key_order=[<span class="hljs-string">"timestamp"</span>, <span class="hljs-string">"level"</span>, <span class="hljs-string">"event"</span>]),
    ],
    context_class=dict,
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=<span class="hljs-literal">True</span>
)

log = structlog.get_logger()

log.info(<span class="hljs-string">"user_logged_in"</span>, user=<span class="hljs-string">"Vinay"</span>, ip=<span class="hljs-string">"192.168.1.1"</span>)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">timestamp=2025-06-20T08:00:00Z level=info event=user_logged_in user=Vinay ip=192.168.1.1
</code></pre>
<h2 id="heading-structured-json-logs">Structured JSON Logs</h2>
<p>In modern deployments, JSON logs are preferred for log aggregators.</p>
<pre><code class="lang-python">structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt=<span class="hljs-string">"iso"</span>),
        structlog.processors.add_log_level,
        structlog.processors.JSONRenderer()
    ],
    ...
)

log = structlog.get_logger()

log.info(<span class="hljs-string">"user_logged_in"</span>, user=<span class="hljs-string">"Vinay"</span>, ip=<span class="hljs-string">"192.168.1.1"</span>)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"timestamp"</span>: <span class="hljs-string">"2025-06-20T08:00:00Z"</span>,
  <span class="hljs-attr">"level"</span>: <span class="hljs-string">"info"</span>,
  <span class="hljs-attr">"event"</span>: <span class="hljs-string">"user_logged_in"</span>,
  <span class="hljs-attr">"user"</span>: <span class="hljs-string">"Vinay"</span>,
  <span class="hljs-attr">"ip"</span>: <span class="hljs-string">"192.168.1.1"</span>
}
</code></pre>
<p>Perfect for ELK stack or CloudWatch ingestion.</p>
<h2 id="heading-adding-contextual-metadata">Adding Contextual Metadata</h2>
<p>Attach global context to loggers, avoiding repeated parameters.</p>
<pre><code class="lang-python">log = structlog.get_logger().bind(service=<span class="hljs-string">"authentication"</span>)

log.info(<span class="hljs-string">"user_logged_in"</span>, user=<span class="hljs-string">"Vinay"</span>)
log.error(<span class="hljs-string">"invalid_token"</span>, user=<span class="hljs-string">"Kumar"</span>)
</code></pre>
<p>Every log will now include <code>service=authentication</code>.</p>
<p><strong>Dynamic context</strong> via <code>threadlocal</code> is possible using <code>structlog.threadlocal.wrap_dict</code>.</p>
<h2 id="heading-custom-event-processors">Custom Event Processors</h2>
<p>Create processors to modify events at runtime.</p>
<p>Example: Add a UUID to every log.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> uuid

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_request_id</span>(<span class="hljs-params">logger, method_name, event_dict</span>):</span>
    event_dict[<span class="hljs-string">"request_id"</span>] = str(uuid.uuid4())
    <span class="hljs-keyword">return</span> event_dict

structlog.configure(
    processors=[
        add_request_id,
        structlog.processors.JSONRenderer()
    ],
    ...
)
</code></pre>
<p><strong>Now every log has a unique</strong> <code>request_id</code>.</p>
<h2 id="heading-production-logging-setup-example">Production Logging Setup Example</h2>
<p>A complete logging pipeline for a FastAPI microservice or API.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">import</span> structlog
<span class="hljs-keyword">from</span> structlog.stdlib <span class="hljs-keyword">import</span> LoggerFactory
<span class="hljs-keyword">from</span> structlog.processors <span class="hljs-keyword">import</span> JSONRenderer, TimeStamper, add_log_level
<span class="hljs-keyword">from</span> structlog.threadlocal <span class="hljs-keyword">import</span> wrap_dict

logging.basicConfig(
    format=<span class="hljs-string">"%(message)s"</span>,
    level=logging.INFO
)

structlog.configure(
    processors=[
        TimeStamper(fmt=<span class="hljs-string">"iso"</span>),
        add_log_level,
        JSONRenderer()
    ],
    context_class=wrap_dict(dict),
    logger_factory=LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=<span class="hljs-literal">True</span>
)

log = structlog.get_logger().bind(service=<span class="hljs-string">"api"</span>)

log.info(<span class="hljs-string">"server_started"</span>, port=<span class="hljs-number">8080</span>)
</code></pre>
<p>This setup:</p>
<ul>
<li><p>Emits JSON logs</p>
</li>
<li><p>Includes timestamps and levels</p>
</li>
<li><p>Supports dynamic context for API endpoints and job workers</p>
</li>
</ul>
<h2 id="heading-performance-considerations">Performance Considerations</h2>
<ul>
<li><p><code>structlog</code> is fast and efficient for JSON logging.</p>
</li>
<li><p>Disabling logs in production:<br />  Use <a target="_blank" href="http://structlog.dev"><code>structlog.dev</code></a><code>.ConsoleRenderer()</code> in dev and <code>JSONRenderer()</code> in prod.</p>
</li>
<li><p>Can integrate with <code>lru_cache</code> or third-party logging transports.</p>
</li>
</ul>
<h2 id="heading-migration-from-logging">Migration From <code>logging</code></h2>
<p>Convert existing <code>logging</code> calls easily:</p>
<p><strong>Before:</strong></p>
<pre><code class="lang-python">logger.info(<span class="hljs-string">"User %s logged in from %s"</span>, user, ip)
</code></pre>
<p><strong>After:</strong></p>
<pre><code class="lang-python">log.info(<span class="hljs-string">"user_logged_in"</span>, user=user, ip=ip)
</code></pre>
<p>Fewer format errors, better structure, no positional argument issues.</p>
<h2 id="heading-testing-logs">Testing Logs</h2>
<p>Unit test log outputs via:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> structlog.testing <span class="hljs-keyword">import</span> capture_logs

<span class="hljs-keyword">with</span> capture_logs() <span class="hljs-keyword">as</span> logs:
    log.info(<span class="hljs-string">"test_event"</span>, status=<span class="hljs-string">"ok"</span>)

<span class="hljs-keyword">assert</span> logs[<span class="hljs-number">0</span>][<span class="hljs-string">"status"</span>] == <span class="hljs-string">"ok"</span>
</code></pre>
<p>Supports clean, testable logging codebases.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<blockquote>
<p><code>structlog</code> is one of Python’s most valuable libraries for modern, structured, JSON-ready logging — yet surprisingly underused in mainstream projects.</p>
</blockquote>
<p>It’s a no-brainer choice for:</p>
<ul>
<li><p>Microservices</p>
</li>
<li><p>FastAPI / Django apps</p>
</li>
<li><p>Serverless functions</p>
</li>
<li><p>Asynchronous job queues</p>
</li>
<li><p>Cloud-native APIs</p>
</li>
<li><p>Data pipelines and ETL jobs</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Ultimate Guide: Unlocking Python's functools Module]]></title><description><![CDATA[Introduction
Python’s standard library is well-known for being "batteries included," but one of its most underrated modules is functools.
If you've worked with decorators, caching, or functional programming patterns, chances are you've encountered fu...]]></description><link>https://blog.naveenpn.com/ultimate-guide-unlocking-pythons-functools-module</link><guid isPermaLink="true">https://blog.naveenpn.com/ultimate-guide-unlocking-pythons-functools-module</guid><category><![CDATA[ #PythonOptimization ]]></category><category><![CDATA[Python]]></category><category><![CDATA[functions]]></category><category><![CDATA[python tips]]></category><category><![CDATA[python developer]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[caching]]></category><category><![CDATA[ #PythonDecorators ]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 22 May 2025 16:52:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750827988532/55f93abf-ae41-462c-8237-bbdf893f2c31.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Python’s standard library is well-known for being <strong>"batteries included,"</strong> but one of its <strong>most underrated</strong> modules is <code>functools</code>.</p>
<p>If you've worked with <strong>decorators, caching, or functional programming patterns</strong>, chances are you've encountered <code>functools</code> without realizing <strong>how powerful it really is</strong>.</p>
<p>This guide <strong>breaks down 8 essential tools</strong>, providing <strong>code examples, real-world use cases, and optimization tips</strong> to make your Python code <strong>faster, cleaner, and smarter</strong>.</p>
<h2 id="heading-what-is-functools"><strong>What is functools?</strong></h2>
<p>The <code>functools</code> module provides <strong>higher-order functions</strong>—functions that act on or return other functions.</p>
<p>It’s <strong>invaluable</strong> for:<br /><strong>Functional programming</strong><br /><strong>Optimizing performance</strong><br /><strong>Caching results</strong><br /><strong>Preserving function metadata</strong><br /><strong>Creating partial functions</strong></p>
<h3 id="heading-importing-functools"><strong>Importing functools</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools
</code></pre>
<p>Now, let's <strong>explore each tool with examples</strong> and <strong>pro tips</strong>.</p>
<h2 id="heading-functoolslrucache-least-recently-used-cache"><strong>functools.lru_cache — Least Recently Used Cache</strong></h2>
<h3 id="heading-what-is-it"><strong>What is it?</strong></h3>
<p>Caches the results of <strong>expensive</strong> or frequently called functions, improving <strong>performance</strong>.</p>
<h3 id="heading-example-caching-fibonacci-computation"><strong>Example: Caching Fibonacci Computation</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-meta">@functools.lru_cache(maxsize=128)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fibonacci</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">if</span> n &lt; <span class="hljs-number">2</span>:
        <span class="hljs-keyword">return</span> n
    <span class="hljs-keyword">return</span> fibonacci(n<span class="hljs-number">-1</span>) + fibonacci(n<span class="hljs-number">-2</span>)

print(fibonacci(<span class="hljs-number">100</span>))  <span class="hljs-comment"># Fast result due to caching</span>
</code></pre>
<h3 id="heading-why-use-it"><strong>Why Use It?</strong></h3>
<p><strong>Prevents redundant recalculations</strong><br /><strong>Speeds up recursive or IO-heavy functions</strong></p>
<h3 id="heading-clearing-cache"><strong>Clearing Cache</strong></h3>
<pre><code class="lang-python">fibonacci.cache_clear()  <span class="hljs-comment"># Clears stored results</span>
</code></pre>
<p><strong>Ideal for memoization</strong> in <strong>data-heavy</strong> computations.</p>
<h2 id="heading-functoolspartial-pre-filling-function-arguments"><strong>functools.partial — Pre-Filling Function Arguments</strong></h2>
<h3 id="heading-what-is-it-1"><strong>What is it?</strong></h3>
<p>Allows <strong>creating a new function</strong> with <strong>fixed arguments</strong>, useful for <strong>callbacks or APIs</strong>.</p>
<h3 id="heading-example-partial-function-for-multiplication"><strong>Example: Partial Function for Multiplication</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-keyword">return</span> a * b

double = functools.partial(multiply, <span class="hljs-number">2</span>)

print(double(<span class="hljs-number">5</span>))  <span class="hljs-comment"># Output: 10</span>
</code></pre>
<h3 id="heading-why-use-it-1"><strong>Why Use It?</strong></h3>
<p><strong>Useful for pre-setting parameters in UI, APIs, and callbacks</strong></p>
<p><strong>Best for reducing repetition</strong> in function calls.</p>
<h2 id="heading-functoolswraps-preserve-function-metadata"><strong>functools.wraps — Preserve Function Metadata</strong></h2>
<h3 id="heading-what-is-it-2"><strong>What is it?</strong></h3>
<p>A <strong>decorator</strong> that <strong>keeps metadata</strong> (<code>__name__</code>, <code>__doc__</code>) of the original function intact.</p>
<h3 id="heading-example-preserving-function-details"><strong>Example: Preserving Function Details</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator</span>(<span class="hljs-params">func</span>):</span>
<span class="hljs-meta">    @functools.wraps(func)</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        <span class="hljs-string">"""Wrapped function"""</span>
        print(<span class="hljs-string">"Before call"</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@my_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>():</span>
    <span class="hljs-string">"""Says hello"""</span>
    print(<span class="hljs-string">"Hello!"</span>)

print(hello.__name__)  <span class="hljs-comment"># Output: hello</span>
print(hello.__doc__)   <span class="hljs-comment"># Output: Says hello</span>
</code></pre>
<h3 id="heading-why-use-it-2"><strong>Why Use It?</strong></h3>
<p><strong>Avoids overwriting function metadata</strong><br /><strong>Essential for debugging &amp; introspection</strong></p>
<p><strong>Crucial when writing custom decorators</strong>.</p>
<h2 id="heading-functoolsreduce-rolling-computation-over-sequences"><strong>functools.reduce — Rolling Computation Over Sequences</strong></h2>
<h3 id="heading-what-is-it-3"><strong>What is it?</strong></h3>
<p>Applies a <strong>rolling computation</strong> to a sequence, reducing it to a <strong>single value</strong>.</p>
<h3 id="heading-example-summing-a-list"><strong>Example: Summing a List</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> functools

numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
result = functools.reduce(<span class="hljs-keyword">lambda</span> x, y: x + y, numbers)
print(result)  <span class="hljs-comment"># Output: 15</span>
</code></pre>
<h3 id="heading-why-use-it-3"><strong>Why Use It?</strong></h3>
<p><strong>Compact way to aggregate sequences</strong><br /><strong>Often used in data processing pipelines</strong></p>
<p><strong>Best for performing cumulative operations</strong>.</p>
<h2 id="heading-functoolscachedproperty-cached-computations"><strong>functools.cached_property — Cached Computations</strong></h2>
<h3 id="heading-what-is-it-4"><strong>What is it?</strong></h3>
<p>Converts a method into a <strong>read-only property</strong> that caches its result <strong>after first access</strong>.</p>
<h3 id="heading-example-efficient-property-calculation"><strong>Example: Efficient Property Calculation</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cached_property

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, radius</span>):</span>
        self.radius = radius

<span class="hljs-meta">    @cached_property</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">area</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Calculating area..."</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-number">3.1415</span> * (self.radius ** <span class="hljs-number">2</span>)

c = Circle(<span class="hljs-number">10</span>)
print(c.area)  <span class="hljs-comment"># Calculates</span>
print(c.area)  <span class="hljs-comment"># Uses cached value</span>
</code></pre>
<h3 id="heading-why-use-it-4"><strong>Why Use It?</strong></h3>
<p><strong>Avoid unnecessary recomputation</strong><br /><strong>Perfect for expensive calculations</strong></p>
<p><strong>Great for database queries and complex properties</strong>.</p>
<h2 id="heading-functoolssingledispatch-type-based-function-dispatching"><strong>functools.singledispatch — Type-Based Function Dispatching</strong></h2>
<h3 id="heading-what-is-it-5"><strong>What is it?</strong></h3>
<p>Creates a <strong>single-dispatch generic function</strong>, changing implementation <strong>based on argument type</strong>.</p>
<h3 id="heading-example-handling-multiple-types-in-a-function"><strong>Example: Handling Multiple Types in a Function</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> singledispatch

<span class="hljs-meta">@singledispatch</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process</span>(<span class="hljs-params">value</span>):</span>
    print(<span class="hljs-string">"Default:"</span>, value)

<span class="hljs-meta">@process.register</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_</span>(<span class="hljs-params">value: int</span>):</span>
    print(<span class="hljs-string">"Integer:"</span>, value)

<span class="hljs-meta">@process.register</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_</span>(<span class="hljs-params">value: str</span>):</span>
    print(<span class="hljs-string">"String:"</span>, value)

process(<span class="hljs-number">10</span>)       <span class="hljs-comment"># Integer: 10</span>
process(<span class="hljs-string">"Hello"</span>)  <span class="hljs-comment"># String: Hello</span>
</code></pre>
<h3 id="heading-why-use-it-5"><strong>Why Use It?</strong></h3>
<p><strong>Cleaner than writing if-else type checks</strong></p>
<p><strong>Ideal for APIs handling different data types</strong>.</p>
<h2 id="heading-functoolssingledispatchmethod-type-based-method-dispatching"><strong>functools.singledispatchmethod — Type-Based Method Dispatching</strong></h2>
<h3 id="heading-what-is-it-6"><strong>What is it?</strong></h3>
<p>Similar to <code>singledispatch</code>, but works <strong>inside classes</strong> for <strong>method dispatching</strong>.</p>
<h3 id="heading-example-class-based-dispatching"><strong>Example: Class-Based Dispatching</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> singledispatchmethod

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Processor</span>:</span>
<span class="hljs-meta">    @singledispatchmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process</span>(<span class="hljs-params">self, arg</span>):</span>
        print(<span class="hljs-string">"Default:"</span>, arg)

<span class="hljs-meta">    @process.register</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_</span>(<span class="hljs-params">self, arg: int</span>):</span>
        print(<span class="hljs-string">"Integer:"</span>, arg)

<span class="hljs-meta">    @process.register</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_</span>(<span class="hljs-params">self, arg: str</span>):</span>
        print(<span class="hljs-string">"String:"</span>, arg)

p = Processor()
p.process(<span class="hljs-number">5</span>)      <span class="hljs-comment"># Integer: 5</span>
p.process(<span class="hljs-string">"test"</span>) <span class="hljs-comment"># String: test</span>
</code></pre>
<h3 id="heading-why-use-it-6"><strong>Why Use It?</strong></h3>
<p><strong>Cleaner method overloading</strong></p>
<p><strong>Best for handling multiple object types in class methods</strong>.</p>
<h2 id="heading-functoolstotalhttpfunctoolstotalordering-auto-generating-comparison-methods"><a target="_blank" href="http://functools.total"><strong>functools.total</strong></a><strong>_ordering — Auto-Generating Comparison Methods</strong></h2>
<h3 id="heading-what-is-it-7"><strong>What is it?</strong></h3>
<p>A <strong>class decorator</strong> that fills in missing <strong>comparison methods</strong> (<code>&lt;, &lt;=, &gt;, &gt;=</code>) based on <strong>those you define</strong>.</p>
<h3 id="heading-example-ordering-objects-by-age"><strong>Example: Ordering Objects by Age</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> total_ordering

<span class="hljs-meta">@total_ordering</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, age</span>):</span>
        self.age = age

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__eq__</span>(<span class="hljs-params">self, other</span>):</span>
        <span class="hljs-keyword">return</span> self.age == other.age

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__lt__</span>(<span class="hljs-params">self, other</span>):</span>
        <span class="hljs-keyword">return</span> self.age &lt; other.age

print(Person(<span class="hljs-number">25</span>) &lt; Person(<span class="hljs-number">30</span>))  <span class="hljs-comment"># True</span>
print(Person(<span class="hljs-number">25</span>) &gt;= Person(<span class="hljs-number">30</span>)) <span class="hljs-comment"># False</span>
</code></pre>
<h3 id="heading-why-use-it-7"><strong>Why Use It?</strong></h3>
<p><strong>Reduces boilerplate when defining custom objects</strong></p>
<p><strong>Best for sorting and ordering objects</strong>.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>The <code>functools</code> module is an <strong>indispensable part of Python's standard library</strong>. Whether you’re <strong>caching results, creating decorators, or optimizing function behavior</strong>, these tools help <strong>make code smarter, cleaner, and more efficient</strong>.</p>
<p>Mastering <code>functools</code> is <strong>essential</strong> for writing high-performance Python applications.</p>
]]></content:encoded></item><item><title><![CDATA[Ultimate Guide to Python’s Pydantic Library]]></title><description><![CDATA[Introduction
Data validation is a critical part of building reliable applications. Whether you're working with APIs, microservices, database models, or configurations, ensuring data integrity is non-negotiable.

Pydantic provides a high-performance, ...]]></description><link>https://blog.naveenpn.com/ultimate-guide-to-pythons-pydantic-library</link><guid isPermaLink="true">https://blog.naveenpn.com/ultimate-guide-to-pythons-pydantic-library</guid><category><![CDATA[#BaseSettings ]]></category><category><![CDATA[pydantic]]></category><category><![CDATA[FastAPI]]></category><category><![CDATA[data validation]]></category><category><![CDATA[python tips]]></category><category><![CDATA[python developer]]></category><category><![CDATA[ #TypeHints ]]></category><category><![CDATA[API development ]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 22 May 2025 16:21:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752851015034/95c9bfe8-2ac9-4cd3-a8ad-fc452f341c64.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Data validation is a critical part of building <strong>reliable applications</strong>. Whether you're working with <strong>APIs, microservices, database models, or configurations</strong>, ensuring data integrity is non-negotiable.</p>
<blockquote>
<p><strong>Pydantic</strong> provides a <strong>high-performance, type-safe, and developer-friendly</strong> approach to <strong>data validation and serialization</strong> using Python type hints. This is one of the reasons why <strong>FastAPI</strong> became so popular—it <strong>automatically parses and validates request data using Pydantic models</strong>.</p>
</blockquote>
<p>This guide covers:</p>
<ul>
<li><p><strong>What Pydantic is and why it matters</strong></p>
</li>
<li><p><strong>Model creation &amp; validation techniques</strong></p>
</li>
<li><p><strong>Advanced features like nested models, settings management, and custom validation</strong></p>
</li>
<li><p><strong>Real-world applications with FastAPI, SQLAlchemy, and environment configuration</strong></p>
</li>
<li><p><strong>Performance comparisons and best practices</strong></p>
</li>
</ul>
<hr />
<h2 id="heading-what-is-pydantic"><strong>What is Pydantic?</strong></h2>
<blockquote>
<p><strong>Pydantic</strong> is a <strong>data validation and settings management</strong> library that leverages <strong>Python type hints</strong> for runtime validation. It <strong>converts input data into expected types</strong> and <strong>raises informative errors when validation fails</strong>.</p>
</blockquote>
<h3 id="heading-why-choose-pydantic"><strong>Why Choose Pydantic?</strong></h3>
<p>✔ <strong>Fast</strong> – Built on top of <strong>Cython</strong> for speed<br />✔ <strong>Type-safe</strong> – Utilizes <strong>Python type hints</strong> for validation<br />✔ <strong>Developer-friendly</strong> – Produces <strong>clean error messages</strong><br />✔ <strong>Framework-ready</strong> – Powers <strong>FastAPI, SQLModel, and other tools</strong><br />✔ <strong>Automatic data parsing and transformation</strong></p>
<h3 id="heading-installation"><strong>Installation</strong></h3>
<pre><code class="lang-bash">pip install pydantic
</code></pre>
<p>For Python 3.12+, install <strong>Pydantic v2</strong>:</p>
<pre><code class="lang-bash">pip install pydantic&gt;=2.0
</code></pre>
<h2 id="heading-basic-model-definition"><strong>Basic Model Definition</strong></h2>
<p>At the heart of Pydantic is the <code>BaseModel</code> class, which provides <strong>automatic type validation and serialization</strong>.</p>
<h3 id="heading-example-creating-a-simple-model"><strong>Example: Creating a Simple Model</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">BaseModel</span>):</span>
    id: int
    name: str
    is_active: bool = <span class="hljs-literal">True</span>

user_data = {<span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"name"</span>: <span class="hljs-string">"Vinay"</span>}
user = User(**user_data)

print(user)
print(user.id)  <span class="hljs-comment"># 1</span>
print(user.is_active)  <span class="hljs-comment"># True</span>
</code></pre>
<p><strong>Automatic type validation and default values</strong></p>
<h2 id="heading-data-validation-in-action"><strong>Data Validation in Action</strong></h2>
<h3 id="heading-example-handling-invalid-data"><strong>Example: Handling Invalid Data</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, ValidationError

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    price: float

<span class="hljs-keyword">try</span>:
    product = Product(name=<span class="hljs-string">"Laptop"</span>, price=<span class="hljs-string">"cheap"</span>)  <span class="hljs-comment"># Invalid price</span>
<span class="hljs-keyword">except</span> ValidationError <span class="hljs-keyword">as</span> e:
    print(e)
</code></pre>
<p>Pydantic <strong>raises informative errors</strong> instead of allowing silent failures:</p>
<pre><code class="lang-plaintext">1 validation error for Product
price
  value is not a valid float (type=type_error.float)
</code></pre>
<h2 id="heading-automatic-type-conversion"><strong>Automatic Type Conversion</strong></h2>
<p>Pydantic can <strong>intelligently coerce types</strong> when possible.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Order</span>(<span class="hljs-params">BaseModel</span>):</span>
    quantity: int

order = Order(quantity=<span class="hljs-string">'5'</span>)  <span class="hljs-comment"># Converts str '5' to int 5</span>
print(order.quantity)  <span class="hljs-comment"># 5</span>
</code></pre>
<p>Helps <strong>avoid common type errors</strong> without extra code.</p>
<h2 id="heading-nested-models"><strong>Nested Models</strong></h2>
<p>Complex data structures can be <strong>modeled efficiently</strong> using nested models.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Address</span>(<span class="hljs-params">BaseModel</span>):</span>
    city: str
    country: str

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    address: Address

customer = Customer(
    name=<span class="hljs-string">"Vinay"</span>,
    address={<span class="hljs-string">"city"</span>: <span class="hljs-string">"Bangalore"</span>, <span class="hljs-string">"country"</span>: <span class="hljs-string">"India"</span>}
)

print(customer.address.city)  <span class="hljs-comment"># Bangalore</span>
</code></pre>
<p><strong>Encapsulates structured data</strong>, making code <strong>modular</strong>.</p>
<h2 id="heading-custom-validation"><strong>Custom Validation</strong></h2>
<p>For more control, use the <code>@validator</code> decorator.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, validator

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    email: str

<span class="hljs-meta">    @validator('email')</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">email_must_contain_at</span>(<span class="hljs-params">cls, v</span>):</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">'@'</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> v:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">'Invalid email format'</span>)
        <span class="hljs-keyword">return</span> v

user = User(name=<span class="hljs-string">"Vinay"</span>, email=<span class="hljs-string">"vinay@example.com"</span>)  <span class="hljs-comment"># Valid</span>
</code></pre>
<p><strong>Ensures critical data follows expected formats</strong>.</p>
<h2 id="heading-optional-fields-and-default-values"><strong>Optional Fields and Default Values</strong></h2>
<p>You can specify <strong>optional fields</strong> using <code>Optional[]</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Blog</span>(<span class="hljs-params">BaseModel</span>):</span>
    title: str
    content: Optional[str] = <span class="hljs-literal">None</span>

post = Blog(title=<span class="hljs-string">"My First Blog"</span>)
print(post.content)  <span class="hljs-comment"># None</span>
</code></pre>
<h2 id="heading-working-with-enums"><strong>Working with Enums</strong></h2>
<p>Pydantic can <strong>validate against Enums</strong> to enforce constraints.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Status</span>(<span class="hljs-params">str, Enum</span>):</span>
    ACTIVE = <span class="hljs-string">'active'</span>
    INACTIVE = <span class="hljs-string">'inactive'</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    status: Status

user = User(name=<span class="hljs-string">"Vinay"</span>, status=<span class="hljs-string">"active"</span>)
print(user.status)  <span class="hljs-comment"># active</span>
</code></pre>
<h2 id="heading-settings-management-with-basesettings"><strong>Settings Management with</strong> <code>BaseSettings</code></h2>
<p>Ideal for <strong>configuration management using environment variables</strong>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseSettings

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Settings</span>(<span class="hljs-params">BaseSettings</span>):</span>
    app_name: str
    debug: bool = <span class="hljs-literal">False</span>

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>:</span>
        env_file = <span class="hljs-string">".env"</span>

settings = Settings()
print(settings.app_name)
</code></pre>
<p><strong>Loads environment variables seamlessly</strong> from <code>.env</code> files.</p>
<p><strong>Example</strong> <code>.env</code> file:</p>
<pre><code class="lang-plaintext">APP_NAME=MyCoolApp
DEBUG=True
</code></pre>
<h2 id="heading-fastapi-pydantic-integration"><strong>FastAPI + Pydantic Integration</strong></h2>
<p>FastAPI uses Pydantic models for <strong>automatic request validation</strong>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel

app = FastAPI()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Item</span>(<span class="hljs-params">BaseModel</span>):</span>
    name: str
    price: float

<span class="hljs-meta">@app.post("/items/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_item</span>(<span class="hljs-params">item: Item</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"item_name"</span>: item.name, <span class="hljs-string">"item_price"</span>: item.price}
</code></pre>
<p><strong>Ensures request data is valid</strong> before processing.</p>
<h2 id="heading-serialization-amp-conversion"><strong>Serialization &amp; Conversion</strong></h2>
<p>Convert models <strong>to JSON or dict format</strong> easily.</p>
<pre><code class="lang-python">user = User(id=<span class="hljs-number">1</span>, name=<span class="hljs-string">"Vinay"</span>)
print(user.json())  <span class="hljs-comment"># JSON representation</span>
print(user.dict())  <span class="hljs-comment"># Dictionary representation</span>
</code></pre>
<h2 id="heading-performance-considerations"><strong>Performance Considerations</strong></h2>
<p><strong>Pydantic v2 is up to 50% faster than v1</strong> due to optimizations.<br /><strong>Uses Cython for improved parsing efficiency</strong>.<br /><strong>Comparison with manual validation techniques shows significant speed gains</strong>.</p>
<h2 id="heading-best-practices"><strong>Best Practices</strong></h2>
<p><strong>Use consistent type hints</strong> for clarity.<br /><strong>Prefer nested models</strong> for structured data.<br /><strong>Leverage BaseSettings</strong> for environment-based configuration.<br /><strong>Use custom validators</strong> to enforce business rules.<br /><strong>Enable</strong> <code>.dict()</code> and <code>.json()</code> for serialization.<br /><strong>Keep models modular and reusable</strong> for scalability.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Pydantic is <strong>more than just a validation library</strong>—it’s a <strong>powerful toolkit for structured, type-safe data handling</strong>.</p>
<ul>
<li><p><strong>Essential for modern Python development</strong>, especially <strong>FastAPI-based applications</strong>.</p>
</li>
<li><p><strong>Improves code reliability</strong> through automatic validation.</p>
</li>
<li><p><strong>Reduces boilerplate</strong> by eliminating manual type-checking.</p>
</li>
</ul>
<p>If you're building robust <strong>APIs, web applications, or data pipelines</strong>, mastering Pydantic <strong>is essential</strong> for clean, predictable data handling.</p>
]]></content:encoded></item><item><title><![CDATA[Task Scheduling and Background Jobs in Python — The Ultimate Guide]]></title><description><![CDATA[Introduction

In modern applications, running tasks automatically at specific intervals is essential. Whether it’s sending notifications, cleaning logs, triggering backups, or fetching data from APIs, Python provides several robust libraries for sche...]]></description><link>https://blog.naveenpn.com/task-scheduling-and-background-jobs-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/task-scheduling-and-background-jobs-in-python-the-ultimate-guide</guid><category><![CDATA[#PythonScheduler ]]></category><category><![CDATA[Python]]></category><category><![CDATA[Task Scheduling]]></category><category><![CDATA[celery]]></category><category><![CDATA[scheduler]]></category><category><![CDATA[background jobs]]></category><category><![CDATA[python tips]]></category><category><![CDATA[pythonautomation]]></category><category><![CDATA[python programming]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 22 May 2025 16:05:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752852801636/e875f245-f205-4e27-a18b-0c9ac38c71be.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<blockquote>
<p>In modern applications, running tasks automatically at specific intervals is essential. Whether it’s <strong>sending notifications, cleaning logs, triggering backups, or fetching data from APIs</strong>, <strong>Python provides several robust libraries</strong> for scheduling tasks efficiently.</p>
</blockquote>
<p>This guide explores <strong>task scheduling and background jobs</strong>, detailing <strong>key libraries, advanced use cases, failure handling, and integration with distributed systems</strong>.</p>
<hr />
<h2 id="heading-what-are-background-jobs-and-task-scheduling"><strong>What Are Background Jobs and Task Scheduling?</strong></h2>
<h3 id="heading-background-jobs"><strong>Background Jobs</strong></h3>
<p>Tasks that run <strong>behind the scenes</strong>, independently of the main program execution.</p>
<h3 id="heading-task-scheduling"><strong>Task Scheduling</strong></h3>
<p>Automating task execution <strong>at a specified time, interval, or after a trigger</strong>.</p>
<h3 id="heading-common-use-cases"><strong>Common Use Cases</strong></h3>
<ul>
<li><p>Automated <strong>report generation</strong></p>
</li>
<li><p>Scheduled <strong>database cleanup</strong></p>
</li>
<li><p><strong>Email and SMS reminders</strong></p>
</li>
<li><p><strong>API data synchronization</strong></p>
</li>
<li><p><strong>Log maintenance</strong></p>
</li>
<li><p><strong>Automated backup processes</strong></p>
</li>
</ul>
<h2 id="heading-popular-python-libraries-for-task-scheduling"><strong>Popular Python Libraries for Task Scheduling</strong></h2>
<h3 id="heading-1-schedule-simple-time-based-scheduling"><strong>1.</strong> <code>schedule</code> — Simple Time-Based Scheduling</h3>
<blockquote>
<p>A lightweight library for scheduling tasks <strong>at fixed intervals or specific times</strong>.</p>
</blockquote>
<h4 id="heading-installation"><strong>Installation</strong></h4>
<pre><code class="lang-bash">pip install schedule
</code></pre>
<h4 id="heading-example-usage"><strong>Example Usage</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> schedule
<span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">job</span>():</span>
    print(<span class="hljs-string">"Task executed!"</span>)

schedule.every(<span class="hljs-number">10</span>).seconds.do(job)  <span class="hljs-comment"># Run every 10 seconds</span>
schedule.every().day.at(<span class="hljs-string">"14:00"</span>).do(job)  <span class="hljs-comment"># Run at 2:00 PM daily</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    schedule.run_pending()
    time.sleep(<span class="hljs-number">1</span>)
</code></pre>
<p><strong>Best for:</strong> Simple scripts, lightweight applications.<br /><strong>Limitations:</strong> No built-in persistent job storage.</p>
<h3 id="heading-2-apscheduler-advanced-python-scheduler"><strong>2. APScheduler — Advanced Python Scheduler</strong></h3>
<p>APScheduler supports:<br />Interval-based scheduling<br />Cron-style scheduling<br />Date-based scheduling<br />Persistent job stores</p>
<h4 id="heading-installation-1"><strong>Installation</strong></h4>
<pre><code class="lang-bash">pip install apscheduler
</code></pre>
<h4 id="heading-interval-based-scheduling"><strong>Interval-Based Scheduling</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> apscheduler.schedulers.background <span class="hljs-keyword">import</span> BackgroundScheduler
<span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_job</span>():</span>
    print(<span class="hljs-string">"Background task running..."</span>)

scheduler = BackgroundScheduler()
scheduler.add_job(my_job, <span class="hljs-string">'interval'</span>, seconds=<span class="hljs-number">5</span>)
scheduler.start()

<span class="hljs-keyword">try</span>:
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        time.sleep(<span class="hljs-number">1</span>)
<span class="hljs-keyword">except</span> (KeyboardInterrupt, SystemExit):
    scheduler.shutdown()
</code></pre>
<p><strong>Best for:</strong> Applications requiring <strong>advanced scheduling or persistent jobs</strong>.<br /><strong>Supports databases</strong> to store jobs reliably.</p>
<h3 id="heading-3-celery-distributed-task-queue"><strong>3. Celery — Distributed Task Queue</strong></h3>
<blockquote>
<p>Celery is a <strong>powerful asynchronous task queue</strong>, ideal for handling scheduled or delayed jobs in <strong>production applications</strong>.</p>
</blockquote>
<h4 id="heading-installation-2"><strong>Installation</strong></h4>
<pre><code class="lang-bash">pip install celery
</code></pre>
<h4 id="heading-example-usage-1"><strong>Example Usage</strong></h4>
<p><a target="_blank" href="http://tasks.py"><strong>tasks.py</strong></a></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery <span class="hljs-keyword">import</span> Celery

app = Celery(<span class="hljs-string">'tasks'</span>, broker=<span class="hljs-string">'redis://localhost:6379/0'</span>)

<span class="hljs-meta">@app.task</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x + y
</code></pre>
<p><strong>Run Worker</strong></p>
<pre><code class="lang-bash">celery -A tasks worker --loglevel=info
</code></pre>
<p><strong>Trigger Task</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> tasks <span class="hljs-keyword">import</span> add
add.delay(<span class="hljs-number">4</span>, <span class="hljs-number">6</span>)
</code></pre>
<p><strong>Best for:</strong> Distributed systems, Django/Flask applications, scaling background tasks.<br />Requires <strong>Redis or RabbitMQ</strong> for message passing.</p>
<h2 id="heading-comparing-task-scheduling-libraries"><strong>Comparing Task Scheduling Libraries</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Library</td><td>Best For</td><td>Persistent Jobs</td><td>External Dependencies</td></tr>
</thead>
<tbody>
<tr>
<td><code>schedule</code></td><td>Simple scripts &amp; lightweight apps</td><td>❌</td><td>None</td></tr>
<tr>
<td><code>APScheduler</code></td><td>Complex scheduling with persistence</td><td>✅</td><td>Optional DB</td></tr>
<tr>
<td><code>Celery</code></td><td>Distributed task management</td><td>✅</td><td>Redis/RabbitMQ</td></tr>
</tbody>
</table>
</div><h2 id="heading-advanced-use-cases"><strong>Advanced Use Cases</strong></h2>
<h3 id="heading-1-distributed-task-scheduling-with-celery-beat"><strong>1. Distributed Task Scheduling with Celery Beat</strong></h3>
<p>Celery Beat allows scheduling tasks periodically <strong>without manual triggers</strong>.</p>
<h4 id="heading-setup-celery-beat"><strong>Setup Celery Beat</strong></h4>
<pre><code class="lang-bash">pip install celery[redis] celery-beat
</code></pre>
<h4 id="heading-taskspyhttptaskspy"><a target="_blank" href="http://tasks.py"><strong>tasks.py</strong></a></h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> celery <span class="hljs-keyword">import</span> Celery

app = Celery(<span class="hljs-string">'tasks'</span>, broker=<span class="hljs-string">'redis://localhost:6379/0'</span>)

<span class="hljs-meta">@app.task</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_reminder</span>():</span>
    print(<span class="hljs-string">"Sending reminder email..."</span>)
</code></pre>
<h4 id="heading-schedule-recurring-tasks"><strong>Schedule Recurring Tasks</strong></h4>
<p>Modify <code>celerybeat-schedule.db</code> to <strong>define recurring jobs</strong>.</p>
<pre><code class="lang-python">CELERY_BEAT_SCHEDULE = {
    <span class="hljs-string">'send-reminder-every-hour'</span>: {
        <span class="hljs-string">'task'</span>: <span class="hljs-string">'tasks.send_reminder'</span>,
        <span class="hljs-string">'schedule'</span>: <span class="hljs-number">3600.0</span>,  <span class="hljs-comment"># Every hour</span>
    }
}
</code></pre>
<p>Used in <strong>web applications</strong> for automated notifications, billing cycles, periodic data processing.</p>
<h3 id="heading-2-kubernetes-cronjobs-for-cloud-based-task-scheduling"><strong>2. Kubernetes CronJobs for Cloud-Based Task Scheduling</strong></h3>
<p>Kubernetes provides <strong>built-in cron job handling</strong> for Python-based scheduled tasks.</p>
<h4 id="heading-example-kubernetes-cronjob-yaml"><strong>Example Kubernetes CronJob YAML</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">batch/v1beta1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">CronJob</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">python-scheduled-task</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">schedule:</span> <span class="hljs-string">"0 * * * *"</span>
  <span class="hljs-attr">jobTemplate:</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">template:</span>
        <span class="hljs-attr">spec:</span>
          <span class="hljs-attr">containers:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">python-job</span>
            <span class="hljs-attr">image:</span> <span class="hljs-string">my-python-image</span>
            <span class="hljs-attr">command:</span> [<span class="hljs-string">"python"</span>, <span class="hljs-string">"/app/my_script.py"</span>]
          <span class="hljs-attr">restartPolicy:</span> <span class="hljs-string">OnFailure</span>
</code></pre>
<p>Best for <strong>cloud-based applications and microservices</strong> requiring scalable task execution.</p>
<h2 id="heading-handling-failures-and-retries"><strong>Handling Failures and Retries</strong></h2>
<h3 id="heading-apscheduler-job-exception-handling"><strong>APScheduler Job Exception Handling</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> apscheduler.schedulers.blocking <span class="hljs-keyword">import</span> BlockingScheduler

scheduler = BlockingScheduler()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">error_prone_task</span>():</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"An error occurred"</span>)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Handled error: <span class="hljs-subst">{e}</span>"</span>)

scheduler.add_job(error_prone_task, <span class="hljs-string">'interval'</span>, seconds=<span class="hljs-number">10</span>)
scheduler.start()
</code></pre>
<p>Ensures <strong>graceful failure handling</strong> in scheduled tasks.</p>
<h3 id="heading-celery-retry-mechanisms"><strong>Celery Retry Mechanisms</strong></h3>
<p>Celery allows automatic retries for failed tasks.</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.task(bind=True, max_retries=3, default_retry_delay=30)</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">unstable_task</span>(<span class="hljs-params">self</span>):</span>
    <span class="hljs-keyword">try</span>:
        risky_operation()
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> exc:
        <span class="hljs-keyword">raise</span> self.retry(exc=exc)
</code></pre>
<p>Prevents tasks from failing permanently due to <strong>network issues or timeouts</strong>.</p>
<h2 id="heading-best-practices"><strong>Best Practices</strong></h2>
<p>Use <strong>APScheduler or Celery</strong> for production environments.<br />Avoid <strong>blocking the main thread</strong>—run jobs in the background.<br />Enable <strong>persistent job stores</strong> for reliability.<br />Implement <strong>logging</strong> to track scheduled job execution.<br />Catch exceptions inside job functions to <strong>prevent crashes</strong>.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Concept</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>schedule</code></td><td>Simple task scheduling for scripts</td></tr>
<tr>
<td><code>APScheduler</code></td><td>Advanced scheduler with persistence</td></tr>
<tr>
<td><code>Celery</code></td><td>Distributed task queue for production</td></tr>
<tr>
<td>Background Jobs</td><td>Tasks running outside the main thread</td></tr>
<tr>
<td>Persistent Job Storage</td><td>Database-based scheduling recovery</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Python <strong>makes task scheduling simple and efficient</strong>, whether through basic interval jobs or <strong>highly scalable distributed systems</strong>. Choosing the right scheduler depends on <strong>application complexity and reliability needs</strong>.</p>
<p>By <strong>mastering task scheduling</strong>, developers can build <strong>scalable applications, automation tools, and real-time services</strong> with ease.</p>
]]></content:encoded></item><item><title><![CDATA[Itertools in Python — The Ultimate Guide]]></title><description><![CDATA[Introduction

When working with iterators, sequences, and data processing in Python, you’ll often repeat patterns for iteration, filtering, or combination. The itertools module simplifies these operations—providing fast, memory-efficient tools to han...]]></description><link>https://blog.naveenpn.com/itertools-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/itertools-in-python-the-ultimate-guide</guid><category><![CDATA[ #PythonItertools]]></category><category><![CDATA[#InfiniteIterators ]]></category><category><![CDATA[Python]]></category><category><![CDATA[itertools]]></category><category><![CDATA[python tips]]></category><category><![CDATA[python programming]]></category><category><![CDATA[lazy-evaluation]]></category><category><![CDATA[combinators]]></category><category><![CDATA[data processing]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 22 May 2025 15:44:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752853018442/b5180c92-ae82-423a-a6ed-d439123b2c05.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<blockquote>
<p>When working with <strong>iterators, sequences, and data processing</strong> in Python, you’ll often repeat patterns for iteration, filtering, or combination. The <code>itertools</code> module <strong>simplifies these operations</strong>—providing <strong>fast, memory-efficient</strong> tools to handle iterators cleanly.</p>
</blockquote>
<p>This guide breaks down <strong>everything you need to know</strong> about <code>itertools</code>, including <strong>key functions, performance benefits, real-world applications, and best practices</strong>.</p>
<hr />
<h2 id="heading-what-is-itertools"><strong>What is itertools?</strong></h2>
<blockquote>
<p><code>itertools</code> is a <strong>standard Python module</strong> that offers a collection of <strong>optimized</strong> iterator functions. These functions operate on <strong>iterables</strong> and return <strong>iterators</strong>, meaning they <strong>don’t load all results at once</strong> but <strong>yield values one by one</strong>, keeping memory usage low.</p>
</blockquote>
<h3 id="heading-why-use-itertools"><strong>Why Use itertools?</strong></h3>
<p>Works <strong>efficiently</strong> with large or infinite sequences.<br /><strong>Lazy evaluation</strong> saves memory by producing results on demand.<br /><strong>Simplifies complex iteration logic</strong> with built-in functions.<br />Supports <strong>functional-style programming</strong>, making loops <strong>cleaner</strong> and <strong>more readable</strong>.</p>
<hr />
<h2 id="heading-core-itertools-functions"><strong>Core itertools Functions</strong></h2>
<h3 id="heading-infinite-iterators"><strong>Infinite Iterators</strong></h3>
<p>These iterators <strong>generate values indefinitely</strong>, unless explicitly stopped.</p>
<h4 id="heading-countstart0-step1-infinite-numeric-sequence"><code>count(start=0, step=1)</code> → Infinite numeric sequence</h4>
<p>Generates an infinite sequence starting from <code>start</code> with increments of <code>step</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> count

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> count(<span class="hljs-number">5</span>, <span class="hljs-number">2</span>):  <span class="hljs-comment"># Starts at 5, increments by 2</span>
    <span class="hljs-keyword">if</span> i &gt; <span class="hljs-number">10</span>:
        <span class="hljs-keyword">break</span>
    print(i)
</code></pre>
<p><strong>Use Case:</strong> Simulating infinite data streams or indexing automatically.</p>
<h4 id="heading-cycleiterable-infinite-repetition-of-an-iterable"><code>cycle(iterable)</code> → Infinite repetition of an iterable</h4>
<p>Loops through an iterable <strong>forever</strong>, restarting after the last element.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> cycle

count = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> cycle([<span class="hljs-string">'A'</span>, <span class="hljs-string">'B'</span>, <span class="hljs-string">'C'</span>]):  <span class="hljs-comment"># Loops through 'A', 'B', 'C'</span>
    <span class="hljs-keyword">if</span> count == <span class="hljs-number">5</span>:  <span class="hljs-comment"># Break to prevent infinite loop</span>
        <span class="hljs-keyword">break</span>
    print(item)
    count += <span class="hljs-number">1</span>
</code></pre>
<p><strong>Use Case:</strong> Rotating through options or circular buffers.</p>
<h4 id="heading-repeatobject-timesnone-repeat-an-object"><code>repeat(object, times=None)</code> → Repeat an object</h4>
<p>Repeats an object <strong>forever</strong> (or <code>times</code> times if specified).</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> repeat

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> repeat(<span class="hljs-string">"Hello"</span>, <span class="hljs-number">3</span>):  <span class="hljs-comment"># Repeats "Hello" 3 times</span>
    print(item)
</code></pre>
<p><strong>Use Case:</strong> Filling default values or generating fixed repetitions.</p>
<h3 id="heading-iterators-that-stop-at-shortest-input"><strong>Iterators That Stop at Shortest Input</strong></h3>
<p>These functions <strong>process multiple sequences</strong> until the shortest one ends.</p>
<h4 id="heading-chainiterables-merge-multiple-iterables"><code>chain(*iterables)</code> → Merge multiple iterables</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> chain

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> chain([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>]):
    print(item)
</code></pre>
<p><strong>Use Case:</strong> Concatenating lists efficiently <strong>without intermediate copies</strong>.</p>
<h4 id="heading-ziplongestiter1-iter2-fillvaluenone-zip-with-missing-values"><code>zip_longest(iter1, iter2, fillvalue=None)</code> → Zip with missing values</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> zip_longest

<span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> zip_longest([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-string">'a'</span>], fillvalue=<span class="hljs-string">'-'</span>):
    print(pair)
</code></pre>
<p><strong>Use Case:</strong> Handling <strong>unequal length</strong> lists gracefully.</p>
<h3 id="heading-filtering-iterators"><strong>Filtering Iterators</strong></h3>
<p>These functions <strong>remove items based on conditions</strong>.</p>
<h4 id="heading-dropwhilepredicate-iterable-drop-items-while-the-condition-is-true"><code>dropwhile(predicate, iterable)</code> → Drop items <strong>while</strong> the condition is true</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> dropwhile

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> dropwhile(<span class="hljs-keyword">lambda</span> x: x &lt; <span class="hljs-number">3</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]):
    print(i)  <span class="hljs-comment"># Skips 1, 2 and starts at 3</span>
</code></pre>
<p><strong>Use Case:</strong> Skipping <strong>irrelevant</strong> prefix data.</p>
<h4 id="heading-takewhilepredicate-iterable-take-items-while-the-condition-is-true"><code>takewhile(predicate, iterable)</code> → Take items <strong>while</strong> the condition is true</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> takewhile

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> takewhile(<span class="hljs-keyword">lambda</span> x: x &lt; <span class="hljs-number">3</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]):
    print(i)  <span class="hljs-comment"># Takes 1, 2 and stops at 3</span>
</code></pre>
<p><strong>Use Case:</strong> Selecting values until a <strong>cutoff</strong> point.</p>
<h4 id="heading-filterfalsepredicate-iterable-filter-out-matching-items"><code>filterfalse(predicate, iterable)</code> → <strong>Filter out</strong> matching items</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> filterfalse

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> filterfalse(<span class="hljs-keyword">lambda</span> x: x % <span class="hljs-number">2</span>, range(<span class="hljs-number">5</span>)):  <span class="hljs-comment"># Keeps even numbers</span>
    print(i)
</code></pre>
<p><strong>Use Case:</strong> Removing unwanted <strong>elements</strong> in one pass.</p>
<h3 id="heading-combinatoric-iterators"><strong>Combinatoric Iterators</strong></h3>
<p>Used for generating <strong>different permutations and combinations</strong> of data.</p>
<h4 id="heading-productiterable-repeat1-cartesian-product"><code>product(iterable, repeat=1)</code> → Cartesian product</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> product

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> product([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>]):
    print(item)
</code></pre>
<p><strong>Use Case:</strong> <strong>Nested loops</strong> simplified using a single function.</p>
<h4 id="heading-permutationsiterable-rnone-generate-all-orderings"><code>permutations(iterable, r=None)</code> → Generate all orderings</h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> permutations

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> permutations(<span class="hljs-string">"AB"</span>, <span class="hljs-number">2</span>):
    print(item)
</code></pre>
<p><strong>Use Case:</strong> Generating possible <strong>password guesses</strong> or reordering items.</p>
<h4 id="heading-combinationsiterable-r-all-combinations-without-replacement"><code>combinations(iterable, r)</code> → All <strong>combinations without replacement</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> combinations

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> combinations([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-number">2</span>):
    print(item)
</code></pre>
<p><strong>Use Case:</strong> Picking <strong>distinct</strong> subsets (e.g., lottery numbers).</p>
<h4 id="heading-combinationswithreplacementiterable-r-combinations-allowing-duplicates"><code>combinations_with_replacement(iterable, r)</code> → Combinations <strong>allowing duplicates</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> combinations_with_replacement

<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> combinations_with_replacement([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], <span class="hljs-number">2</span>):
    print(item)
</code></pre>
<p><strong>Use Case:</strong> Generating <strong>possible ways</strong> to fill slots in a grid.</p>
<h2 id="heading-performance-insights"><strong>Performance Insights</strong></h2>
<p><strong>Memory Efficiency</strong> → Itertools <strong>uses iterators</strong>, avoiding unnecessary storage.<br /><strong>Lazy Evaluation</strong> → Results <strong>stream</strong> instead of being loaded all at once.<br /><strong>Optimized Algorithms</strong> → Faster than manual loops, especially with large datasets.</p>
<h2 id="heading-advanced-use-cases"><strong>Advanced Use Cases</strong></h2>
<p><strong>Efficient Log Processing</strong> → Filtering, parsing, and merging large log files.<br /><strong>Data Science &amp; AI</strong> → Generating dataset variations efficiently.<br /><strong>Simulation &amp; Testing</strong> → Creating test inputs using <code>product()</code> and <code>permutations()</code>.<br /><strong>Functional Programming</strong> → Enhancing <code>map()</code>, <code>reduce()</code>, and <code>filter()</code>.</p>
<h2 id="heading-best-practices"><strong>Best Practices</strong></h2>
<p><strong>Use itertools instead of manual loops</strong> → Cleaner, <strong>more readable</strong> code.<br /><strong>Combine functions</strong> → Filter, merge, and process efficiently.<br /><strong>Limit infinite iterators</strong> → Always use <code>break</code> conditions.<br /><strong>Convert to lists only when needed</strong> → Avoid unnecessary memory usage.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p><code>itertools</code> is one of <strong>Python’s most powerful modules</strong> for handling <strong>iteration patterns efficiently</strong>. Whether you’re processing <strong>large datasets</strong>, creating <strong>test cases</strong>, or optimizing <strong>loops</strong>, mastering <code>itertools</code> <strong>significantly improves performance and readability</strong>.</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Descriptors in Python — The Ultimate Guide]]></title><description><![CDATA[Introduction
In Python, everything is an object, and attribute access is a fundamental operation. But what if you wanted to control how an attribute behaves when accessed, modified, or deleted? That’s where descriptors come in. They’re a powerful, of...]]></description><link>https://blog.naveenpn.com/descriptors-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/descriptors-in-python-the-ultimate-guide</guid><category><![CDATA[#PythonDescriptors ]]></category><category><![CDATA[#OOPinPython ]]></category><category><![CDATA[#PropertyDecorator ]]></category><category><![CDATA[#DataDescriptors ]]></category><category><![CDATA[#NonDataDescriptors ]]></category><category><![CDATA[Python]]></category><category><![CDATA[Python Classes In Pune]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Thu, 22 May 2025 15:29:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752855991670/028dd5a8-9389-4d7b-84d5-b03ca30269de.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In Python, <strong>everything is an object</strong>, and attribute access is a fundamental operation. But what if you wanted to control <strong>how</strong> an attribute behaves when accessed, modified, or deleted? That’s where <strong>descriptors</strong> come in. They’re a powerful, often overlooked feature that let you <strong>manage attribute access dynamically</strong> within a class.</p>
<p>This guide provides a <strong>complete overview of descriptors</strong>, including <strong>how they work, when to use them, and best practices for clean, reusable implementations.</strong></p>
<h2 id="heading-what-are-descriptors">What Are Descriptors?</h2>
<p>A <strong>descriptor</strong> is a Python object that implements one or more of the following special methods:</p>
<ul>
<li><p><code>__get__(self, instance, owner)</code>: Called when the attribute is accessed.</p>
</li>
<li><p><code>__set__(self, instance, value)</code>: Called when the attribute is assigned a new value.</p>
</li>
<li><p><code>__delete__(self, instance)</code>: Called when the attribute is deleted with <code>del</code>.</p>
</li>
</ul>
<h3 id="heading-how-attribute-lookup-works">How Attribute Lookup Works</h3>
<p>When an attribute is accessed in Python, the interpreter follows <strong>a specific lookup order</strong>:</p>
<ol>
<li><p><strong>Instance dictionary (</strong><code>__dict__</code>) → If the attribute exists in the instance, Python retrieves it directly.</p>
</li>
<li><p><strong>Class attributes</strong> → If not found in the instance, Python checks the class definition for the attribute.</p>
</li>
<li><p><strong>Descriptors</strong> → If the attribute is a descriptor, Python invokes its special methods (<code>__get__</code>, <code>__set__</code>, <code>__delete__</code>).</p>
</li>
<li><p><strong>Inheritance chain</strong> → If still unresolved, Python searches in parent classes.</p>
</li>
<li><p><strong>Fallback</strong> → If the attribute is missing everywhere, Python raises an <code>AttributeError</code>.</p>
</li>
</ol>
<p>Thus, descriptors <strong>override</strong> instance attributes under certain conditions, making them extremely powerful for <strong>fine-grained control</strong> over attribute behavior.</p>
<hr />
<h2 id="heading-why-use-descriptors">Why Use Descriptors?</h2>
<p>Descriptors provide <strong>precise control</strong> over attribute access, enabling:</p>
<ul>
<li><p><strong>Validation and type-checking</strong> → Ensure values meet specific criteria.</p>
</li>
<li><p><strong>Computed properties</strong> → Define attributes that calculate values dynamically.</p>
</li>
<li><p><strong>Resource management</strong> → Handle opening/closing connections, caching values.</p>
</li>
<li><p><strong>Access control</strong> → Implement authentication and logging for sensitive attributes.</p>
</li>
<li><p><strong>Lazy evaluation</strong> → Defer expensive computations until needed.</p>
</li>
</ul>
<h3 id="heading-built-in-python-features-using-descriptors">Built-in Python Features Using Descriptors</h3>
<p>Several core Python features use descriptors internally:</p>
<ul>
<li><p><code>property()</code> → Implements computed attributes.</p>
</li>
<li><p><code>staticmethod()</code> &amp; <code>classmethod()</code> → Modify method behavior at the class level.</p>
</li>
<li><p><code>functools.cached_property</code> → Implements efficient caching.</p>
</li>
</ul>
<h2 id="heading-the-descriptor-protocol-methods">The Descriptor Protocol Methods</h2>
<h3 id="heading-getself-instance-owner-handles-attribute-retrieval"><code>__get__(self, instance, owner)</code> → Handles attribute retrieval</h3>
<p>Called when the attribute is accessed on an instance.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyDescriptor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__get__</span>(<span class="hljs-params">self, instance, owner</span>):</span>
        print(<span class="hljs-string">"Getting value"</span>)
        <span class="hljs-keyword">return</span> instance._value  <span class="hljs-comment"># Return stored value</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    value = MyDescriptor()

obj = MyClass()
obj.value  <span class="hljs-comment"># Calls __get__()</span>
</code></pre>
<hr />
<h3 id="heading-setself-instance-value-handles-attribute-assignment"><code>__set__(self, instance, value)</code> → Handles attribute assignment</h3>
<p>Called when an attribute is set. Often used for <strong>validation</strong> or <strong>transformations</strong>.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyDescriptor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__set__</span>(<span class="hljs-params">self, instance, value</span>):</span>
        <span class="hljs-keyword">if</span> value &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Negative value not allowed"</span>)
        print(<span class="hljs-string">"Setting value"</span>)
        instance._value = value  <span class="hljs-comment"># Store validated value</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    value = MyDescriptor()

obj = MyClass()
obj.value = <span class="hljs-number">10</span>  <span class="hljs-comment"># Calls __set__()</span>
</code></pre>
<hr />
<h3 id="heading-deleteself-instance-handles-attribute-deletion"><code>__delete__(self, instance)</code> → Handles attribute deletion</h3>
<p>Called when an attribute is deleted using <code>del</code>.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyDescriptor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__delete__</span>(<span class="hljs-params">self, instance</span>):</span>
        print(<span class="hljs-string">"Deleting value"</span>)
        <span class="hljs-keyword">del</span> instance._value  <span class="hljs-comment"># Remove stored value</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    value = MyDescriptor()

obj = MyClass()
<span class="hljs-keyword">del</span> obj.value  <span class="hljs-comment"># Calls __delete__()</span>
</code></pre>
<hr />
<h2 id="heading-data-vs-non-data-descriptors">Data vs Non-Data Descriptors</h2>
<ul>
<li><p><strong>Data descriptors</strong> → Implement <strong>both</strong> <code>__get__</code> <strong>and</strong> (<code>__set__</code> or <code>__delete__</code>).</p>
</li>
<li><p><strong>Non-data descriptors</strong> → Implement <strong>only</strong> <code>__get__</code>.</p>
</li>
</ul>
<p>Data descriptors have <strong>higher precedence</strong> than instance attributes, while non-data descriptors do <strong>not</strong>.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NonData</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__get__</span>(<span class="hljs-params">self, instance, owner</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Non-data descriptor"</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Data</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__get__</span>(<span class="hljs-params">self, instance, owner</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Data descriptor"</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__set__</span>(<span class="hljs-params">self, instance, value</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span>:</span>
    nd = NonData()
    d = Data()

e = Example()
e.nd = <span class="hljs-string">"Instance attribute"</span>
print(e.nd)  <span class="hljs-comment"># 'Instance attribute' because NonData is non-data descriptor</span>
print(e.d)   <span class="hljs-comment"># 'Data descriptor' because Data takes precedence</span>
</code></pre>
<h2 id="heading-how-pythons-built-ins-use-descriptors">How Python’s Built-ins Use Descriptors</h2>
<h3 id="heading-property-example"><code>property()</code> example</h3>
<p>The <code>property()</code> function <strong>creates a descriptor internally</strong>, which manages attribute access.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, radius</span>):</span>
        self._radius = radius

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_radius</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self._radius

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">set_radius</span>(<span class="hljs-params">self, value</span>):</span>
        <span class="hljs-keyword">if</span> value &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Negative radius not allowed"</span>)
        self._radius = value

    radius = property(get_radius, set_radius)

c = Circle(<span class="hljs-number">5</span>)
print(c.radius)  <span class="hljs-comment"># Calls get_radius()</span>
c.radius = <span class="hljs-number">10</span>    <span class="hljs-comment"># Calls set_radius()</span>
</code></pre>
<h2 id="heading-real-world-use-cases-for-descriptors">Real-World Use Cases for Descriptors</h2>
<h3 id="heading-1-validation-ensure-values-meet-requirements"><strong>1. Validation</strong> → Ensure values meet requirements</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PositiveNumber</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__set__</span>(<span class="hljs-params">self, instance, value</span>):</span>
        <span class="hljs-keyword">if</span> value &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Only positive values allowed"</span>)
        instance._value = value

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Account</span>:</span>
    balance = PositiveNumber()

a = Account()
a.balance = <span class="hljs-number">-100</span>  <span class="hljs-comment"># Raises ValueError</span>
</code></pre>
<h3 id="heading-2-caching-store-expensive-computations"><strong>2. Caching</strong> → Store expensive computations</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CachedProperty</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__get__</span>(<span class="hljs-params">self, instance, owner</span>):</span>
        <span class="hljs-keyword">if</span> <span class="hljs-string">"_cached_value"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> instance.__dict__:
            instance._cached_value = instance.expensive_computation()
        <span class="hljs-keyword">return</span> instance._cached_value

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    cache = CachedProperty()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">expensive_computation</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Running expensive computation..."</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-number">42</span>

obj = MyClass()
print(obj.cache)  <span class="hljs-comment"># Runs computation once</span>
print(obj.cache)  <span class="hljs-comment"># Returns cached value</span>
</code></pre>
<h3 id="heading-3-logging-and-debugging-track-attribute-changes"><strong>3. Logging and Debugging</strong> → Track attribute changes</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoggingDescriptor</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__set__</span>(<span class="hljs-params">self, instance, value</span>):</span>
        print(<span class="hljs-string">f"Setting <span class="hljs-subst">{instance.__class__.__name__}</span>.value to <span class="hljs-subst">{value}</span>"</span>)
        instance._value = value

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    value = LoggingDescriptor()

obj = MyClass()
obj.value = <span class="hljs-number">100</span>  <span class="hljs-comment"># Logs assignment</span>
</code></pre>
<h2 id="heading-best-practices">Best Practices</h2>
<ul>
<li><p>Use descriptors when <strong>multiple classes</strong> need <strong>shared attribute logic</strong>.</p>
</li>
<li><p>Keep descriptor classes <strong>modular and reusable</strong>.</p>
</li>
<li><p>Use <code>property()</code> for <strong>simpler cases</strong>.</p>
</li>
<li><p>Avoid excessive complexity—<strong>only use descriptors when truly necessary</strong>.</p>
</li>
</ul>
<h2 id="heading-limitations">Limitations</h2>
<ul>
<li><p><strong>Increased complexity</strong> → Can make code harder to debug.</p>
</li>
<li><p><strong>Performance impact</strong> → Descriptors add <strong>a level of indirection</strong> in attribute lookup.</p>
</li>
<li><p><strong>Not always necessary</strong> → <code>property()</code> is often sufficient.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Descriptors are <strong>one of Python’s most powerful mechanisms</strong> for controlling attribute behavior. They are used internally in Python <strong>for built-in features</strong> like <code>property()</code>, and they provide <strong>fine-grained control</strong> over attribute access.</p>
<p>By <strong>mastering descriptors</strong>, you gain <strong>a deeper understanding of Python internals</strong>—preparing you to build <strong>robust frameworks, APIs, and high-performance applications</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[How Python’s Global Interpreter Lock (GIL) Affects Multithreading — The Ultimate Guide]]></title><description><![CDATA[When people hear Python supports multithreading, they often assume it can run multiple threads truly in parallel. But there’s a twist — the Global Interpreter Lock (GIL) changes how threading works in Python’s CPython implementation.
This guide break...]]></description><link>https://blog.naveenpn.com/how-pythons-global-interpreter-lock-gil-affects-multithreading-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/how-pythons-global-interpreter-lock-gil-affects-multithreading-the-ultimate-guide</guid><category><![CDATA[ #GlobalInterpreterLock ]]></category><category><![CDATA[#PythonConcurrency ]]></category><category><![CDATA[ #PythonPerformance]]></category><category><![CDATA[Python]]></category><category><![CDATA[GILABET88]]></category><category><![CDATA[multithreading]]></category><category><![CDATA[multiprocessing]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 20 May 2025 04:30:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752856314841/a89f5d15-96b6-4e36-ac36-4433bedbdccf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When people hear Python supports multithreading, they often assume it can run multiple threads truly in parallel. But there’s a twist — the <strong>Global Interpreter Lock (GIL)</strong> changes how threading works in Python’s CPython implementation.</p>
<p>This guide breaks down what the GIL is, how it affects multithreading, when it matters, and how to work around it for high-performance applications.</p>
<h2 id="heading-what-is-the-global-interpreter-lock-gil">What is the Global Interpreter Lock (GIL)?</h2>
<blockquote>
<p>The <strong>GIL</strong> is a mutex (mutual exclusion lock) used in <strong>CPython</strong> (the standard Python implementation) to ensure that <strong>only one thread executes Python bytecode at a time</strong>, even on multi-core processors.</p>
</blockquote>
<p>In short:</p>
<ul>
<li><p>Even if you start multiple threads in Python, only one of them can execute Python code at a given instant.</p>
</li>
<li><p>Other threads must wait their turn.</p>
</li>
</ul>
<p><strong>Why?</strong><br />To make Python’s memory management (which isn’t thread-safe) safe and simple, the GIL was introduced.</p>
<h2 id="heading-how-does-the-gil-work">How Does the GIL Work?</h2>
<ul>
<li><p>Python interpreter holds the <strong>GIL</strong> while executing Python bytecode.</p>
</li>
<li><p>It periodically releases and reacquires the lock (after a certain number of bytecode instructions or time intervals).</p>
</li>
<li><p>Native code (C extensions like NumPy) can temporarily release the GIL to run in parallel.</p>
</li>
</ul>
<h2 id="heading-gil-and-multithreading-in-python">GIL and Multithreading in Python</h2>
<p>While you can create multiple threads in Python using the <code>threading</code> module, the GIL prevents them from executing Python code simultaneously in multiple cores.</p>
<p><strong>I/O-bound programs</strong> (like file reading, network requests) benefit from multithreading because threads waiting on I/O operations release the GIL.</p>
<p><strong>CPU-bound programs</strong> (like heavy computations) don’t benefit much because threads fight for the GIL.</p>
<h2 id="heading-example-multithreading-in-python">Example: Multithreading in Python</h2>
<p><strong>Code:</strong></p>
<pre><code class="lang-plaintext">pythonCopyEditimport threading
import time

def task():
    print(f"Thread {threading.current_thread().name} starting")
    time.sleep(1)
    print(f"Thread {threading.current_thread().name} done")

threads = []
for _ in range(5):
    t = threading.Thread(target=task)
    t.start()
    threads.append(t)

for t in threads:
    t.join()
</code></pre>
<p>Runs fine because <code>time.sleep()</code> releases the GIL.</p>
<h2 id="heading-gil-vs-multiprocessing">GIL vs Multiprocessing</h2>
<p>The <strong>multiprocessing</strong> module bypasses the GIL by creating separate Python processes, each with its own interpreter and memory space.</p>
<p>Perfect for CPU-bound tasks<br />True parallelism using multiple cores</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-plaintext">pythonCopyEditfrom multiprocessing import Process

def compute():
    print("Heavy CPU task")

processes = []
for _ in range(5):
    p = Process(target=compute)
    p.start()
    processes.append(p)

for p in processes:
    p.join()
</code></pre>
<h2 id="heading-when-is-the-gil-a-problem">When is the GIL a Problem?</h2>
<ul>
<li><p>CPU-bound programs with multithreading</p>
</li>
<li><p>Real-time data analysis with heavy calculations</p>
</li>
<li><p>High-performance scientific computing in pure Python</p>
</li>
</ul>
<p>For I/O-bound programs (networking, file I/O), the GIL is usually harmless because threads spend time waiting for external resources.</p>
<h2 id="heading-how-to-work-around-the-gil">How to Work Around the GIL</h2>
<p>Use <strong>multiprocessing</strong> for CPU-heavy parallelism<br />Use <strong>C extensions</strong> (NumPy, SciPy) which release the GIL during heavy computations<br />Move critical code to <strong>Cython</strong> and release the GIL<br />Use alternative interpreters like <strong>Jython</strong> (Java-based) or <strong>IronPython</strong> (.NET-based) — these don’t have a GIL</p>
<h2 id="heading-why-not-remove-the-gil">Why Not Remove the GIL?</h2>
<p>Removing the GIL would:</p>
<ul>
<li><p>Complicate memory management</p>
</li>
<li><p>Reduce performance for single-threaded programs (which most Python code is)</p>
</li>
</ul>
<p>The trade-off hasn’t yet been worth it for CPython’s primary user base.</p>
<p><strong>Note:</strong> There are experimental forks like <strong>nogil</strong> by Sam Gross attempting a GIL-free Python, but it’s not mainstream yet.</p>
<h2 id="heading-summary-table">Summary Table</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Concept</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>GIL</td><td>A lock ensuring only one Python thread runs at a time in CPython</td></tr>
<tr>
<td>Multithreading</td><td>Multiple threads within a process, but only one executes Python code at once</td></tr>
<tr>
<td>Multiprocessing</td><td>Multiple processes each with its own GIL and memory space</td></tr>
<tr>
<td>I/O-bound</td><td>Multithreading effective — threads release GIL while waiting for I/O</td></tr>
<tr>
<td>CPU-bound</td><td>Use multiprocessing — threads fight for the GIL</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion">Conclusion</h2>
<p>The <strong>Global Interpreter Lock (GIL)</strong> is one of the most misunderstood features of Python. While it limits multithreading in CPU-bound programs, it protects memory integrity and simplifies the interpreter.</p>
<p>Knowing when it matters and how to work around it using multiprocessing, C extensions, or Cython will help you build scalable, performant Python applications.</p>
]]></content:encoded></item><item><title><![CDATA[Data Classes in Python — The Ultimate Guide]]></title><description><![CDATA[Managing classes with lots of repetitive code—like __init__, __repr__, and __eq__—can be tedious and error-prone. Python’s data classes, introduced in Python 3.7 via PEP 557, eliminate this by automatically generating these methods for you.

This lea...]]></description><link>https://blog.naveenpn.com/data-classes-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/data-classes-in-python-the-ultimate-guide</guid><category><![CDATA[#DataClasses ]]></category><category><![CDATA[python tips]]></category><category><![CDATA[clean code]]></category><category><![CDATA[ #TypeHints ]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Code Quality]]></category><category><![CDATA[python development]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 20 May 2025 04:15:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752856483615/3e407892-925f-4ac8-8c7b-e975a1a65536.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Managing <strong>classes with lots of repetitive code</strong>—like <code>__init__</code>, <code>__repr__</code>, and <code>__eq__</code>—can be tedious and error-prone. Python’s <strong>data classes</strong>, introduced in <strong>Python 3.7 via PEP 557</strong>, eliminate this by <strong>automatically generating these methods</strong> for you.</p>
</blockquote>
<p>This leads to <strong>cleaner, more readable code</strong> with <strong>less effort</strong>.</p>
<h2 id="heading-what-are-data-classes"><strong>What Are Data Classes?</strong></h2>
<p>Data classes are a Python feature using the <code>@dataclass</code> <strong>decorator</strong> that automatically adds <strong>special methods</strong> (<code>__init__</code>, <code>__repr__</code>, <code>__eq__</code>, etc.) to a class <strong>based on its attributes</strong>.</p>
<h3 id="heading-without-data-classes"><strong>Without Data Classes:</strong></h3>
<p>Before data classes, developers had to write these methods <strong>manually</strong>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name: str, age: int</span>):</span>
        self.name = name
        self.age = age

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"Person(name=<span class="hljs-subst">{self.name}</span>, age=<span class="hljs-subst">{self.age}</span>)"</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__eq__</span>(<span class="hljs-params">self, other</span>):</span>
        <span class="hljs-keyword">return</span> isinstance(other, Person) <span class="hljs-keyword">and</span> self.name == other.name <span class="hljs-keyword">and</span> self.age == other.age
</code></pre>
<h3 id="heading-with-data-classes"><strong>With Data Classes:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> dataclass

<span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    name: str
    age: int
</code></pre>
<p>Python <strong>auto-generates</strong> all those methods for you!</p>
<h2 id="heading-why-use-data-classes"><strong>Why Use Data Classes?</strong></h2>
<p><strong>Less Boilerplate</strong> → No need to manually define <code>__init__</code>, <code>__repr__</code>, or <code>__eq__</code>.<br /><strong>Better Readability</strong> → Cleaner class definitions, making code more understandable.<br /><strong>Built-in Methods</strong> → Automatically enables object comparison and representation.<br /><strong>Type Hint Integration</strong> → Fields require <strong>type annotations</strong>, improving clarity.<br /><strong>Easy Defaults and Customization</strong> → Allows <strong>default values</strong> and flexible behavior.</p>
<h3 id="heading-analogy"><strong>Analogy:</strong></h3>
<p>Think of <strong>data classes</strong> as <strong>a recipe template</strong>:</p>
<ul>
<li><p>Instead of writing instructions <strong>from scratch</strong>, the template <strong>pre-fills common sections</strong>.</p>
</li>
<li><p>This <strong>saves time</strong> while ensuring consistency.</p>
</li>
</ul>
<h2 id="heading-creating-a-basic-data-class"><strong>Creating a Basic Data Class</strong></h2>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> dataclass

<span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span>:</span>
    x: float
    y: float
</code></pre>
<h3 id="heading-usage-example"><strong>Usage Example:</strong></h3>
<pre><code class="lang-python">p1 = Point(<span class="hljs-number">1.5</span>, <span class="hljs-number">2.5</span>)
print(p1)  <span class="hljs-comment"># Output: Point(x=1.5, y=2.5)</span>
</code></pre>
<h2 id="heading-default-values-and-field-customization"><strong>Default Values and Field Customization</strong></h2>
<p>Assign <strong>default values</strong> to attributes:</p>
<pre><code class="lang-python"><span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    name: str
    age: int = <span class="hljs-number">30</span>  <span class="hljs-comment"># Default age is 30</span>
</code></pre>
<p>Use <code>field()</code> for <strong>more control</strong>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> field

<span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    name: str
    age: int = field(default=<span class="hljs-number">30</span>)
    active: bool = field(default=<span class="hljs-literal">True</span>, repr=<span class="hljs-literal">False</span>)  <span class="hljs-comment"># Excluded from repr</span>
</code></pre>
<h2 id="heading-immutable-data-classes-frozentrue"><strong>Immutable Data Classes (</strong><code>frozen=True</code>)</h2>
<p>Making a data class <strong>immutable</strong> (read-only):</p>
<pre><code class="lang-python"><span class="hljs-meta">@dataclass(frozen=True)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span>:</span>
    x: float
    y: float
</code></pre>
<h3 id="heading-example"><strong>Example:</strong></h3>
<pre><code class="lang-python">p = Point(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
p.x = <span class="hljs-number">10</span>  <span class="hljs-comment"># Raises FrozenInstanceError</span>
</code></pre>
<h3 id="heading-analogy-1"><strong>Analogy:</strong></h3>
<p>An <strong>immutable data class</strong> is like <strong>a movie ticket</strong>—once printed, <strong>you can't modify it</strong>.</p>
<h2 id="heading-post-initialization-with-postinit"><strong>Post-Initialization with</strong> <code>__post_init__</code></h2>
<p>Sometimes, additional <strong>logic</strong> is required <strong>after initialization</strong>:</p>
<pre><code class="lang-python"><span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    name: str
    age: int

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__post_init__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.age &lt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Age must be positive"</span>)
</code></pre>
<h3 id="heading-example-1"><strong>Example:</strong></h3>
<pre><code class="lang-python">p = Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">-5</span>)  <span class="hljs-comment"># Raises ValueError</span>
</code></pre>
<h3 id="heading-analogy-2"><strong>Analogy:</strong></h3>
<p>Think of <code>__post_init__</code> like <strong>a security check</strong> before entering an event:</p>
<ul>
<li>After getting <strong>a ticket</strong>, security <strong>checks if you're eligible</strong> to enter.</li>
</ul>
<h2 id="heading-comparison-and-ordering"><strong>Comparison and Ordering</strong></h2>
<p>By <strong>default</strong>, <code>__eq__</code> is generated.<br />To <strong>enable ordering (</strong><code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>), use <code>order=True</code>:</p>
<pre><code class="lang-python"><span class="hljs-meta">@dataclass(order=True)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span>:</span>
    x: int
    y: int
</code></pre>
<h3 id="heading-example-2"><strong>Example:</strong></h3>
<pre><code class="lang-python">p1 = Point(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
p2 = Point(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>)

print(p1 &lt; p2)  <span class="hljs-comment"># Output: True</span>
</code></pre>
<h3 id="heading-analogy-3"><strong>Analogy:</strong></h3>
<p>Ordering objects is like <strong>sorting students by grades</strong>—Python automatically determines <strong>which comes first</strong>.</p>
<h2 id="heading-using-data-classes-with-inheritance"><strong>Using Data Classes with Inheritance</strong></h2>
<p>Data classes <strong>support inheritance</strong>:</p>
<pre><code class="lang-python"><span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span>(<span class="hljs-params">Person</span>):</span>
    employee_id: int
</code></pre>
<h3 id="heading-example-3"><strong>Example:</strong></h3>
<pre><code class="lang-python">emp = Employee(<span class="hljs-string">"John"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">1001</span>)
print(emp)  <span class="hljs-comment"># Output: Employee(name='John', age=30, employee_id=1001)</span>
</code></pre>
<h3 id="heading-analogy-4"><strong>Analogy:</strong></h3>
<p>Inheritance is like <strong>a new car model built on a previous design</strong>—it keeps <strong>existing features</strong> while <strong>adding new ones</strong>.</p>
<h2 id="heading-best-practices"><strong>Best Practices</strong></h2>
<p><strong>Use data classes for objects that primarily store data</strong>.<br /><strong>Avoid putting complex logic inside data classes</strong>—keep them simple.<br /><strong>Use</strong> <code>frozen=True</code> for immutable objects when necessary.<br /><strong>Use type hints for all fields</strong> to improve clarity and prevent errors.<br /><strong>Use</strong> <code>field()</code> for more precise customization (e.g., default values, exclusion from <code>repr</code>).<br /><strong>Combine with the</strong> <code>typing</code> module for advanced field types (e.g., <code>List[str]</code>, <code>Optional[int]</code>).</p>
<h2 id="heading-summary-table"><strong>Summary Table</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>@dataclass</code></td><td>Decorator that auto-generates class methods</td></tr>
<tr>
<td><code>field()</code></td><td>Customizes individual field behavior</td></tr>
<tr>
<td><code>frozen=True</code></td><td>Makes instances immutable</td></tr>
<tr>
<td><code>order=True</code></td><td>Enables ordering (<code>&lt;</code>, <code>&gt;</code>, etc.)</td></tr>
<tr>
<td><code>post_init</code></td><td>Runs additional setup after initialization</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Data classes <strong>simplify writing classes that primarily store data</strong> by <strong>eliminating repetitive code</strong> and <strong>automatically generating useful methods</strong>. They work <strong>seamlessly with Python’s type hints</strong> and provide <strong>powerful customization options</strong>.</p>
<h3 id="heading-why-use-them"><strong>Why Use Them?</strong></h3>
<p><strong>Reduces boilerplate</strong> → No need to manually define methods.<br /><strong>Enhances clarity</strong> → Code is more readable and maintainable.<br /><strong>Provides built-in features</strong> → Supports comparison, ordering, and defaults.</p>
<p>Start <strong>converting your plain classes to data classes</strong>—you'll <strong>save time and make your code cleaner</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Type Hints and mypy in Python — The Ultimate Guide]]></title><description><![CDATA[Writing clean, readable, and bug-free code is essential for developers. Python’s dynamic typing allows flexibility but can make debugging challenging—especially in large projects.
Enter Type Hints—Python’s optional way to introduce static typing, and...]]></description><link>https://blog.naveenpn.com/type-hints-and-mypy-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/type-hints-and-mypy-in-python-the-ultimate-guide</guid><category><![CDATA[ #TypeHints ]]></category><category><![CDATA[#StaticTyping]]></category><category><![CDATA[ #TypeChecking]]></category><category><![CDATA[Python]]></category><category><![CDATA[Mypy]]></category><category><![CDATA[python tips]]></category><category><![CDATA[clean code]]></category><category><![CDATA[python development]]></category><category><![CDATA[Code Quality]]></category><category><![CDATA[Software Engineering]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 20 May 2025 03:56:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752856583594/43e3ede5-6d20-4657-99d5-72e62fbe88af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Writing <strong>clean, readable, and bug-free code</strong> is essential for developers. Python’s <strong>dynamic typing</strong> allows flexibility but can make debugging <strong>challenging</strong>—especially in large projects.</p>
<p>Enter <strong>Type Hints</strong>—Python’s optional way to introduce <strong>static typing</strong>, and <strong>mypy</strong>, a popular static type checker that catches type-related errors <strong>before runtime</strong>.</p>
<p>This guide walks through <strong>why type hints matter</strong>, how to <strong>implement them effectively</strong>, and how to use <strong>mypy to improve code quality</strong>.</p>
</blockquote>
<h2 id="heading-what-are-type-hints-in-python"><strong>What Are Type Hints in Python?</strong></h2>
<p>Type hints allow developers to <strong>declare expected data types</strong> for function arguments, return values, and variables. Introduced in Python <strong>3.5 via PEP 484</strong>, type hints don’t change <strong>how Python executes code</strong> but improve documentation and tooling support.</p>
<h3 id="heading-example"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name: str</span>) -&gt; str:</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>"</span>
</code></pre>
<p>In this example:</p>
<ul>
<li><p><code>name</code> is expected to be a <strong>string</strong>.</p>
</li>
<li><p>The function <strong>returns</strong> a string.</p>
</li>
</ul>
<h3 id="heading-analogy"><strong>Analogy:</strong></h3>
<p>Think of <strong>type hints</strong> as <strong>traffic signs</strong>:</p>
<ul>
<li><p>They don’t control driving <strong>but guide you</strong> in the right direction.</p>
</li>
<li><p>Just like a "Speed Limit: 60 km/h" sign helps maintain order, <strong>type hints help organize and clarify code expectations</strong>.</p>
</li>
</ul>
<h2 id="heading-why-use-type-hints"><strong>Why Use Type Hints?</strong></h2>
<p><strong>Improved Readability</strong> → Helps developers understand expected data types.<br /><strong>Better Tooling Support</strong> → Enables smart autocompletion and refactoring.<br /><strong>Early Bug Detection</strong> → Static analyzers like <code>mypy</code> catch type mismatches before runtime.<br /><strong>Easier Maintenance</strong> → Large codebases become <strong>less error-prone and easier to navigate</strong>.</p>
<h3 id="heading-analogy-1"><strong>Analogy:</strong></h3>
<p>Imagine a <strong>recipe book</strong> specifying <strong>exact measurements</strong>:</p>
<ul>
<li><p>Instead of "Add sugar," it states "Add <strong>100g of sugar</strong>."</p>
</li>
<li><p>This <strong>removes ambiguity</strong>, ensuring clarity and correctness.</p>
</li>
</ul>
<h2 id="heading-basic-syntax-of-type-hints"><strong>Basic Syntax of Type Hints</strong></h2>
<h3 id="heading-function-arguments-and-return-types"><strong>Function Arguments and Return Types:</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a: int, b: int</span>) -&gt; int:</span>
    <span class="hljs-keyword">return</span> a + b
</code></pre>
<h3 id="heading-annotating-variables"><strong>Annotating Variables:</strong></h3>
<pre><code class="lang-python">age: int = <span class="hljs-number">25</span>
names: list[str] = [<span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Bob"</span>]
</code></pre>
<h3 id="heading-optional-types-may-be-none"><strong>Optional Types (May Be</strong> <code>None</code>):</h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Optional

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">id: int</span>) -&gt; Optional[str]:</span>
    <span class="hljs-keyword">if</span> id == <span class="hljs-number">1</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Alice"</span>
    <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
</code></pre>
<h3 id="heading-analogy-2"><strong>Analogy:</strong></h3>
<p>Think of <strong>optional types</strong> like restaurant reservations.</p>
<ul>
<li><p>If the restaurant is full, you might <strong>get a table (</strong><code>str</code>).</p>
</li>
<li><p>If unavailable, you get <strong>None</strong>—indicating no reservation.</p>
</li>
</ul>
<h2 id="heading-advanced-type-hints"><strong>Advanced Type Hints</strong></h2>
<h3 id="heading-union-multiple-possible-types"><strong>Union (Multiple Possible Types)</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process</span>(<span class="hljs-params">data: Union[str, bytes]</span>):</span>
    ...
</code></pre>
<p>Accepts either <strong>a string or bytes</strong>, enhancing flexibility.</p>
<h3 id="heading-type-aliases-custom-type-names"><strong>Type Aliases (Custom Type Names)</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> List

Vector = List[float]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scale</span>(<span class="hljs-params">vec: Vector, scalar: float</span>) -&gt; Vector:</span>
    ...
</code></pre>
<p>Simplifies readability by using <code>Vector</code> instead of <code>List[float]</code>.</p>
<h3 id="heading-generics-working-with-any-type"><strong>Generics (Working With Any Type)</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypeVar, List

T = TypeVar(<span class="hljs-string">'T'</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">first_element</span>(<span class="hljs-params">lst: List[T]</span>) -&gt; T:</span>
    <span class="hljs-keyword">return</span> lst[<span class="hljs-number">0</span>]
</code></pre>
<p>This function <strong>works with any list type</strong>, improving reusability.</p>
<h3 id="heading-callable-for-functions-as-arguments"><strong>Callable (For Functions as Arguments)</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Callable

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_func</span>(<span class="hljs-params">f: Callable[[int, int], int], a: int, b: int</span>) -&gt; int:</span>
    <span class="hljs-keyword">return</span> f(a, b)
</code></pre>
<p>Accepts <strong>any function</strong> that takes two integers and returns an integer.</p>
<h3 id="heading-analogy-3"><strong>Analogy:</strong></h3>
<p>Think of <strong>type aliases</strong> like <strong>nicknames</strong>:</p>
<ul>
<li>Instead of calling someone <strong>Jonathan</strong>, you can refer to them as <strong>Jon</strong>—making conversations <strong>shorter and clearer</strong>.</li>
</ul>
<h2 id="heading-what-is-mypy"><strong>What is</strong> <code>mypy</code>?</h2>
<p><code>mypy</code> is a <strong>static type checker</strong> for Python. It reads <strong>type hints</strong> and reports <strong>type errors without running the program</strong>.</p>
<h3 id="heading-installation"><strong>Installation:</strong></h3>
<pre><code class="lang-sh">pip install mypy
</code></pre>
<h3 id="heading-running-mypy-on-your-code"><strong>Running mypy on your code:</strong></h3>
<pre><code class="lang-sh">mypy myscript.py
</code></pre>
<h2 id="heading-using-mypy-to-catch-bugs-early"><strong>Using</strong> <code>mypy</code> to Catch Bugs Early</h2>
<h3 id="heading-example-incorrect-assignment"><strong>Example (Incorrect Assignment):</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a: int, b: int</span>) -&gt; int:</span>
    <span class="hljs-keyword">return</span> a + b

result: str = add(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>)  <span class="hljs-comment"># Incorrect assignment</span>
</code></pre>
<p>Running <code>mypy</code> will flag this <strong>as an error</strong>:</p>
<pre><code class="lang-plaintext">error: Incompatible types in assignment (expression has type "int", variable has type "str")
</code></pre>
<h3 id="heading-analogy-4"><strong>Analogy:</strong></h3>
<p>Think of <strong>mypy</strong> like a <strong>spell-checker</strong>:</p>
<ul>
<li>It <strong>doesn’t change</strong> your writing but <strong>points out mistakes</strong> before publication.</li>
</ul>
<h2 id="heading-gradual-typing-and-type-comments"><strong>Gradual Typing and Type Comments</strong></h2>
<p>Python lets developers <strong>add type hints gradually</strong>.</p>
<p>For <strong>legacy code (Python &lt;3.5)</strong>, use <strong>type comments</strong>:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-comment"># type: (int, int) -&gt; int</span>
    <span class="hljs-keyword">return</span> a + b
</code></pre>
<h2 id="heading-type-checking-with-third-party-libraries"><strong>Type Checking with Third-Party Libraries</strong></h2>
<p>Some libraries <strong>don’t come with type hints</strong>.<br />Solutions include:</p>
<ul>
<li><p><strong>Stub files</strong></p>
</li>
<li><p><strong>Tools like</strong> <code>typeshed</code> or <code>typing_extensions</code></p>
</li>
</ul>
<h2 id="heading-best-practices-for-type-hints-and-mypy"><strong>Best Practices for Type Hints and</strong> <code>mypy</code></h2>
<p>✔ <strong>Add type hints</strong> to public functions first.<br />✔ <strong>Use</strong> <code>Optional</code> for variables that can be <code>None</code>.<br />✔ <strong>Integrate</strong> <code>mypy</code> in CI/CD pipelines to enforce type safety.<br />✔ <strong>Complement with tests</strong>—type hints <strong>help but don’t replace testing</strong>.<br />✔ <strong>Use</strong> <code># type: ignore</code> sparingly to silence unnecessary errors.<br />✔ <strong>Avoid excessive generics</strong> unless absolutely necessary.</p>
<h2 id="heading-summary-table"><strong>Summary Table</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Concept</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Type Hints</strong></td><td>Optional static typing in Python</td></tr>
<tr>
<td><strong>mypy</strong></td><td>Static type checker for Python</td></tr>
<tr>
<td><strong>Optional[T]</strong></td><td>A type that can be <code>T</code> or <code>None</code></td></tr>
<tr>
<td><strong>Union</strong></td><td>Allows multiple possible types</td></tr>
<tr>
<td><strong>TypeVar</strong></td><td>Generic type variable</td></tr>
<tr>
<td><strong>Callable</strong></td><td>Function or method type</td></tr>
<tr>
<td><strong># type: ignore</strong></td><td>Directive to silence <code>mypy</code> errors</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Type hints and <code>mypy</code> <strong>bring Python closer</strong> to statically typed languages, helping developers <strong>catch bugs before runtime</strong> and write <strong>maintainable, scalable code</strong>.</p>
<p>While <strong>optional</strong>, adopting type annotations <strong>improves collaboration, readability, and tooling support</strong>, especially in <strong>large projects</strong>.</p>
<p>Start <strong>adding type hints today</strong>, run <strong>mypy checks regularly</strong>, and watch your code <strong>become more robust and developer-friendly</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Asynchronous Programming with asyncio in Python — The Ultimate Guide]]></title><description><![CDATA[What is Asynchronous Programming?

Asynchronous programming allows a program to start a task and move on to another before the first one finishes. Unlike synchronous programming, where operations execute sequentially, asynchronous programs switch bet...]]></description><link>https://blog.naveenpn.com/asynchronous-programming-with-asyncio-in-python-the-ultimate-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/asynchronous-programming-with-asyncio-in-python-the-ultimate-guide</guid><category><![CDATA[ #PythonAsync]]></category><category><![CDATA[FastPython ]]></category><category><![CDATA[Python]]></category><category><![CDATA[asyncio]]></category><category><![CDATA[asynchronous programming]]></category><category><![CDATA[hire python developers]]></category><category><![CDATA[Event Loop]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[concurrency]]></category><category><![CDATA[python tips]]></category><category><![CDATA[python tutorial]]></category><category><![CDATA[async/await]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 20 May 2025 03:31:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752856728548/0f264fc2-0b83-4123-910b-9b2d9afd3288.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-asynchronous-programming"><strong>What is Asynchronous Programming?</strong></h2>
<blockquote>
<p>Asynchronous programming allows a program to start a task and move on to another <strong>before the first one finishes</strong>. Unlike synchronous programming, where operations <strong>execute sequentially</strong>, asynchronous programs <strong>switch between tasks efficiently</strong>, making them ideal for handling I/O-bound operations like <strong>file access, database queries, or API requests</strong>.</p>
</blockquote>
<h3 id="heading-simple-comparison"><strong>Simple Comparison:</strong></h3>
<ul>
<li><p>🔴 <strong>Synchronous</strong> → Do <strong>one thing</strong> at a time.</p>
</li>
<li><p>🟢 <strong>Asynchronous</strong> → Handle <strong>multiple tasks</strong> together without blocking execution.</p>
</li>
</ul>
<h3 id="heading-analogy"><strong>Analogy:</strong></h3>
<p>Think of <strong>cooking a meal</strong>:</p>
<ul>
<li><p><strong>Synchronous Cooking:</strong> You wait for water to boil <strong>before</strong> chopping vegetables.</p>
</li>
<li><p><strong>Asynchronous Cooking:</strong> You chop vegetables <strong>while</strong> water is boiling, making efficient use of time.</p>
</li>
</ul>
<h2 id="heading-why-do-we-need-asynchronous-programming"><strong>Why Do We Need Asynchronous Programming?</strong></h2>
<p>Traditional <strong>synchronous</strong> code waits for each task to finish before moving to the next. If one task involves waiting (like reading a file or querying a web API), the entire program pauses.</p>
<p>Asynchronous programming <strong>solves this problem</strong>, making operations more efficient:</p>
<h3 id="heading-advantages-of-async-programming"><strong>Advantages of Async Programming:</strong></h3>
<ul>
<li><p><strong>Better Performance</strong> → Ideal for I/O-bound tasks.</p>
</li>
<li><p><strong>Handles Concurrent Operations</strong> → Supports thousands of simultaneous tasks.</p>
</li>
<li><p><strong>Essential for Web Servers &amp; APIs</strong> → Helps process multiple user requests.</p>
</li>
</ul>
<h2 id="heading-introduction-to-pythons-asyncio-module"><strong>Introduction to Python’s</strong> <code>asyncio</code> Module</h2>
<blockquote>
<p>Python’s <code>asyncio</code> module allows writing <strong>concurrent code</strong> using <code>async</code> and <code>await</code>. It manages an <strong>event loop</strong>, which dispatches tasks <strong>without waiting</strong> for each to complete.</p>
</blockquote>
<h3 id="heading-key-features-of-asyncio"><strong>Key Features of</strong> <code>asyncio</code>:</h3>
<p><strong>Non-blocking I/O operations</strong><br /><strong>Efficient execution of multiple tasks</strong><br /><strong>Ideal for web servers, bots, and data pipelines</strong><br /><strong>Available from Python 3.4+, with enhancements in later versions</strong></p>
<h2 id="heading-core-concepts-in-asyncio"><strong>Core Concepts in</strong> <code>asyncio</code></h2>
<h3 id="heading-event-loop"><strong>Event Loop</strong></h3>
<p>The <strong>event loop</strong> runs asynchronous tasks and manages callbacks, controlling when tasks execute.</p>
<h4 id="heading-example"><strong>Example:</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.sleep(<span class="hljs-number">1</span>))
loop.close()
</code></pre>
<h3 id="heading-analogy-1"><strong>Analogy:</strong></h3>
<p>Think of an <strong>orchestra conductor</strong> managing multiple musicians. 🎶<br />The <strong>event loop</strong> ensures each musician (task) plays at the right time <strong>without unnecessary pauses</strong>.</p>
<h3 id="heading-coroutines"><strong>Coroutines</strong></h3>
<p>A <strong>coroutine</strong> is a special function defined with <code>async def</code> that can be <strong>paused and resumed later</strong>.</p>
<h4 id="heading-example-1"><strong>Example:</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_coroutine</span>():</span>
    print(<span class="hljs-string">"Start"</span>)
    <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">2</span>)
    print(<span class="hljs-string">"End"</span>)
</code></pre>
<h3 id="heading-analogy-2"><strong>Analogy:</strong></h3>
<p>Imagine <strong>watching a TV show</strong>:</p>
<ul>
<li><p>You <strong>pause</strong> (<code>await</code>) to grab a snack.</p>
</li>
<li><p>The show <strong>resumes</strong> where you left off <strong>without restarting</strong>.</p>
</li>
</ul>
<h3 id="heading-await"><strong>Await</strong></h3>
<p>Use <code>await</code> to <strong>pause a coroutine</strong> until an asynchronous operation finishes.</p>
<h4 id="heading-example-2"><strong>Example:</strong></h4>
<pre><code class="lang-python"><span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)
</code></pre>
<h3 id="heading-analogy-3"><strong>Analogy:</strong></h3>
<p>Think of <strong>ordering food at a restaurant</strong>:</p>
<ul>
<li><p>You <strong>place an order</strong> (<code>async function</code>).</p>
</li>
<li><p>The kitchen <strong>prepares food</strong> while you wait (<code>await</code>).</p>
</li>
<li><p>Your <strong>order arrives</strong> (<code>execution resumes</code>).</p>
</li>
</ul>
<h2 id="heading-creating-and-running-coroutines"><strong>Creating and Running Coroutines</strong></h2>
<h3 id="heading-example-3"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">say_hello</span>():</span>
    print(<span class="hljs-string">"Hello"</span>)
    <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">1</span>)
    print(<span class="hljs-string">"World"</span>)

asyncio.run(say_hello())
</code></pre>
<h3 id="heading-output"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">Hello  
World
</code></pre>
<p>This example <strong>waits 1 second</strong> before printing "World" but does <strong>not block</strong> execution.</p>
<h2 id="heading-running-multiple-coroutines-concurrently"><strong>Running Multiple Coroutines Concurrently</strong></h2>
<p>Use <code>asyncio.gather()</code> to <strong>run multiple tasks in parallel</strong>.</p>
<h3 id="heading-example-4"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">task</span>(<span class="hljs-params">name, delay</span>):</span>
    print(<span class="hljs-string">f"Task <span class="hljs-subst">{name}</span> started"</span>)
    <span class="hljs-keyword">await</span> asyncio.sleep(delay)
    print(<span class="hljs-string">f"Task <span class="hljs-subst">{name}</span> finished"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-keyword">await</span> asyncio.gather(
        task(<span class="hljs-string">"A"</span>, <span class="hljs-number">2</span>),
        task(<span class="hljs-string">"B"</span>, <span class="hljs-number">1</span>),
        task(<span class="hljs-string">"C"</span>, <span class="hljs-number">3</span>)
    )

asyncio.run(main())
</code></pre>
<h3 id="heading-output-1"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">Task A started  
Task B started  
Task C started  
Task B finished  
Task A finished  
Task C finished
</code></pre>
<h3 id="heading-analogy-4"><strong>Analogy:</strong></h3>
<p><strong>Washing clothes:</strong></p>
<ul>
<li><p><strong>Washing machine</strong> runs (<code>Task A</code>).</p>
</li>
<li><p><strong>You start vacuuming</strong> (<code>Task B</code>).</p>
</li>
<li><p><strong>Oven preheats</strong> (<code>Task C</code>).<br />  Tasks run <strong>independently without waiting for each other to finish</strong>!</p>
</li>
</ul>
<h2 id="heading-using-tasks-asynciocreatetask"><strong>Using Tasks (</strong><code>asyncio.create_task</code>)</h2>
<p>A <strong>Task</strong> is a <strong>wrapper around a coroutine</strong> that runs in the event loop.</p>
<h3 id="heading-example-5"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display</span>(<span class="hljs-params">number</span>):</span>
    <span class="hljs-keyword">await</span> asyncio.sleep(<span class="hljs-number">2</span>)
    print(<span class="hljs-string">f"Number: <span class="hljs-subst">{number}</span>"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    task1 = asyncio.create_task(display(<span class="hljs-number">1</span>))
    task2 = asyncio.create_task(display(<span class="hljs-number">2</span>))
    <span class="hljs-keyword">await</span> task1
    <span class="hljs-keyword">await</span> task2

asyncio.run(main())
</code></pre>
<h2 id="heading-handling-asynchronous-io-operations"><strong>Handling Asynchronous I/O Operations</strong></h2>
<p>Ideal for <strong>network requests, file handling, and database queries</strong>.</p>
<h3 id="heading-example-6"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> aiohttp
<span class="hljs-keyword">import</span> asyncio

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch</span>(<span class="hljs-params">url</span>):</span>
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiohttp.ClientSession() <span class="hljs-keyword">as</span> session:
        <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> session.get(url) <span class="hljs-keyword">as</span> response:
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.text()

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    html = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://example.com'</span>)
    print(html)

asyncio.run(main())
</code></pre>
<h3 id="heading-install-aiohttp"><strong>Install</strong> <code>aiohttp</code>:</h3>
<pre><code class="lang-sh">pip install aiohttp
</code></pre>
<h3 id="heading-analogy-5"><strong>Analogy:</strong></h3>
<p>Fetching <strong>live stock prices</strong>—instead of waiting for daily updates, you get <strong>real-time values</strong>.</p>
<h2 id="heading-exception-handling-in-asyncio"><strong>Exception Handling in</strong> <code>asyncio</code></h2>
<p>Use <code>try-except</code> inside async functions.</p>
<h3 id="heading-example-7"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">risky</span>():</span>
    <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Oops!"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-keyword">try</span>:
        <span class="hljs-keyword">await</span> risky()
    <span class="hljs-keyword">except</span> ValueError <span class="hljs-keyword">as</span> e:
        print(<span class="hljs-string">f"Caught: <span class="hljs-subst">{e}</span>"</span>)

asyncio.run(main())
</code></pre>
<h3 id="heading-output-2"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">Caught: Oops!
</code></pre>
<h2 id="heading-common-real-world-use-cases"><strong>Common Real-World Use Cases</strong></h2>
<p><strong>Web servers</strong> (FastAPI, Sanic)<br /><strong>Chat applications</strong> (real-time messaging)<br /><strong>Web scrapers</strong> (data extraction)<br /><strong>IoT data streams</strong> (sensor readings)<br /><strong>Database access</strong> (async queries)<br /><strong>Concurrent API calls</strong> (speed up requests)</p>
<h2 id="heading-limitations-of-asyncio"><strong>Limitations of</strong> <code>asyncio</code></h2>
<p><strong>Not for CPU-bound tasks</strong> → Use <strong>multiprocessing</strong> instead.<br /><strong>Can be complex</strong> if <strong>poorly structured</strong>.<br /><strong>Requires Python 3.7+</strong> for <a target="_blank" href="http://asyncio.run"><code>asyncio.run</code></a><code>()</code>.</p>
<h2 id="heading-best-practices-for-asyncio"><strong>Best Practices for</strong> <code>asyncio</code></h2>
<p><strong>Use</strong> <a target="_blank" href="http://asyncio.run"><code>asyncio.run</code></a><code>()</code> to start the event loop.<br /><strong>Always use</strong> <code>await</code> inside coroutines.<br /><strong>Structure code cleanly</strong> to avoid messy callbacks.<br /><strong>Use</strong> <code>asyncio.gather()</code> for multiple tasks.<br /><strong>Prefer async libraries</strong> (<code>aiohttp</code>, <code>aiomysql</code>, <code>aioredis</code>).</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p><strong>Asynchronous programming with</strong> <code>asyncio</code> supercharges Python applications, enabling them to handle thousands of concurrent operations <strong>efficiently</strong>. Mastering <code>asyncio</code> prepares you for <strong>building scalable, high-performance applications</strong>—whether it’s <strong>servers, data pipelines, or real-time apps</strong>.</p>
<h3 id="heading-start-using-asyncio-today-and-unlock-the-full-potential-of-async-programming"><strong>Start using</strong> <code>asyncio</code> today, and unlock the full potential of async programming!</h3>
]]></content:encoded></item><item><title><![CDATA[Context Managers in Python — A Complete Guide]]></title><description><![CDATA[Python is known for its clean syntax and philosophy of writing readable, efficient, and maintainable code. One feature that embodies this principle is the Context Manager. It simplifies resource management, such as opening and closing files, managing...]]></description><link>https://blog.naveenpn.com/context-managers-in-python-a-complete-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/context-managers-in-python-a-complete-guide</guid><category><![CDATA[ #WithStatement ]]></category><category><![CDATA[Python]]></category><category><![CDATA[python tips]]></category><category><![CDATA[contextmanagers]]></category><category><![CDATA[python programming]]></category><category><![CDATA[clean code]]></category><category><![CDATA[resource management]]></category><category><![CDATA[hire python developers]]></category><category><![CDATA[PythonBestPractices]]></category><category><![CDATA[contextlib]]></category><category><![CDATA[Code Quality]]></category><category><![CDATA[learn python]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Tue, 20 May 2025 03:15:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752854708569/40d85a29-2ee6-425c-9d13-4b9ed690b2aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>Python is known for its <strong>clean syntax</strong> and philosophy of writing <strong>readable, efficient, and maintainable code</strong>. One feature that embodies this principle is the <strong>Context Manager</strong>. It simplifies <strong>resource management</strong>, such as opening and closing files, managing database connections, or handling network sockets.</p>
</blockquote>
<h2 id="heading-what-is-a-context-manager"><strong>What is a Context Manager?</strong></h2>
<blockquote>
<p>A <strong>Context Manager</strong> in Python helps manage resources efficiently, ensuring they are <strong>allocated and released</strong> exactly when needed. You’ve likely used <strong>the</strong> <code>with</code> statement for file handling:</p>
</blockquote>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> open(<span class="hljs-string">'example.txt'</span>, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> file:
    content = file.read()
</code></pre>
<h3 id="heading-how-it-works"><strong>How It Works:</strong></h3>
<ul>
<li><p><code>open()</code> <strong>returns a file object</strong>.</p>
</li>
<li><p>The <code>with</code> statement ensures the <strong>file automatically closes</strong> when the code block ends.</p>
</li>
<li><p><strong>Prevents resource leaks</strong> and eliminates the need for <code>file.close()</code>.</p>
</li>
</ul>
<h3 id="heading-everyday-analogy"><strong>Everyday Analogy:</strong></h3>
<p>Think of renting a bicycle for an hour:</p>
<ul>
<li><p>You <strong>enter</strong> the rental shop (<code>__enter__()</code>).</p>
</li>
<li><p>You ride the bicycle for an hour.</p>
</li>
<li><p>When you return the bike, the shop <strong>handles cleanup</strong> (<code>__exit__()</code>), ensuring everything is properly stored for the next user.</p>
</li>
</ul>
<h2 id="heading-why-use-context-managers"><strong>Why Use Context Managers?</strong></h2>
<h3 id="heading-automatic-resource-management"><strong>Automatic Resource Management</strong></h3>
<p>Resources like files, databases, or network sockets are <strong>automatically released</strong> when no longer needed.</p>
<h3 id="heading-cleaner-readable-code"><strong>Cleaner, Readable Code</strong></h3>
<p>Removes the need for <strong>manual exception handling</strong> or cleanup logic.</p>
<h3 id="heading-avoids-resource-leaks"><strong>Avoids Resource Leaks</strong></h3>
<p>Ensures proper <strong>resource deallocation</strong>, even in case of errors.</p>
<h3 id="heading-encapsulates-setup-amp-teardown-logic"><strong>Encapsulates Setup &amp; Teardown Logic</strong></h3>
<p>Keeps operations <strong>self-contained</strong>, reducing redundant code.</p>
<h2 id="heading-how-do-context-managers-work"><strong>How Do Context Managers Work?</strong></h2>
<p>A <strong>context manager</strong> implements <strong>two key methods</strong>:</p>
<ul>
<li><p><code>__enter__(self)</code> → <strong>Setup</strong> operations (like opening a file or database connection).</p>
</li>
<li><p><code>__exit__(self, exc_type, exc_value, traceback)</code> → <strong>Cleanup</strong> operations (closing resources, handling errors).</p>
</li>
</ul>
<p>When the <code>with</code> block starts, Python <strong>calls</strong> <code>__enter__()</code>.<br />When the block <strong>finishes (successfully or with an exception)</strong>, Python <strong>calls</strong> <code>__exit__()</code>.</p>
<h2 id="heading-built-in-context-managers"><strong>Built-in Context Managers</strong></h2>
<p>Python <strong>provides many built-in context managers</strong>:</p>
<ul>
<li><p><code>open()</code> → <strong>File handling</strong></p>
</li>
<li><p><code>threading.Lock()</code> → <strong>Thread synchronization</strong></p>
</li>
<li><p><code>decimal.localcontext()</code> → <strong>Decimal arithmetic precision</strong></p>
</li>
</ul>
<h3 id="heading-example"><strong>Example:</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> threading

lock = threading.Lock()
<span class="hljs-keyword">with</span> lock:
    print(<span class="hljs-string">"Thread-safe operation here"</span>)
</code></pre>
<h2 id="heading-creating-custom-context-managers"><strong>Creating Custom Context Managers</strong></h2>
<h3 id="heading-using-a-class-enter-amp-exit"><strong>Using a Class (</strong><code>__enter__()</code> &amp; <code>__exit__()</code>)</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyContext</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__enter__</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Entering context"</span>)
        <span class="hljs-keyword">return</span> self

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__exit__</span>(<span class="hljs-params">self, exc_type, exc_value, traceback</span>):</span>
        print(<span class="hljs-string">"Exiting context"</span>)

<span class="hljs-keyword">with</span> MyContext():
    print(<span class="hljs-string">"Inside with block"</span>)
</code></pre>
<h3 id="heading-output"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">Entering context  
Inside with block  
Exiting context
</code></pre>
<h3 id="heading-using-contextlib-function-based-context-managers"><strong>Using</strong> <code>contextlib</code> (Function-based Context Managers)</h3>
<p>Python’s <code>contextlib</code> module allows <strong>generator-based context managers</strong>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> contextlib <span class="hljs-keyword">import</span> contextmanager

<span class="hljs-meta">@contextmanager</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_context</span>():</span>
    print(<span class="hljs-string">"Setup"</span>)
    <span class="hljs-keyword">yield</span>
    print(<span class="hljs-string">"Cleanup"</span>)

<span class="hljs-keyword">with</span> my_context():
    print(<span class="hljs-string">"Inside block"</span>)
</code></pre>
<h3 id="heading-output-1"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">Setup  
Inside block  
Cleanup
</code></pre>
<h2 id="heading-exception-handling-in-context-managers"><strong>Exception Handling in Context Managers</strong></h2>
<p>The <code>__exit__()</code> method <strong>handles exceptions gracefully</strong>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IgnoreZeroDivision</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__enter__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__exit__</span>(<span class="hljs-params">self, exc_type, exc_value, traceback</span>):</span>
        <span class="hljs-keyword">if</span> exc_type <span class="hljs-keyword">is</span> ZeroDivisionError:
            print(<span class="hljs-string">"ZeroDivisionError caught!"</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>  <span class="hljs-comment"># Suppress exception</span>

<span class="hljs-keyword">with</span> IgnoreZeroDivision():
    result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>
    print(<span class="hljs-string">"After division"</span>)  <span class="hljs-comment"># This won't be executed</span>
</code></pre>
<h3 id="heading-output-2"><strong>Output:</strong></h3>
<pre><code class="lang-plaintext">ZeroDivisionError caught!
</code></pre>
<p><strong>Benefit:</strong> Prevents program crashes due to specific errors.</p>
<h2 id="heading-real-world-use-cases-for-context-managers"><strong>Real-World Use Cases for Context Managers</strong></h2>
<h3 id="heading-file-operations"><strong>File Operations</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">with</span> open(<span class="hljs-string">"data.txt"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    content = file.read()
</code></pre>
<h3 id="heading-database-connections"><strong>Database Connections</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sqlite3

<span class="hljs-keyword">with</span> sqlite3.connect(<span class="hljs-string">"my_database.db"</span>) <span class="hljs-keyword">as</span> conn:
    cursor = conn.cursor()
    cursor.execute(<span class="hljs-string">"SELECT * FROM users"</span>)
</code></pre>
<h3 id="heading-network-socket-handling"><strong>Network Socket Handling</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> socket

<span class="hljs-keyword">with</span> socket.socket(socket.AF_INET, socket.SOCK_STREAM) <span class="hljs-keyword">as</span> s:
    s.connect((<span class="hljs-string">"example.com"</span>, <span class="hljs-number">80</span>))
    s.sendall(<span class="hljs-string">b"Hello, server!"</span>)
</code></pre>
<h3 id="heading-thread-locks-multithreading"><strong>Thread Locks (Multithreading)</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> threading

lock = threading.Lock()
<span class="hljs-keyword">with</span> lock:
    print(<span class="hljs-string">"Thread-safe operation"</span>)
</code></pre>
<h2 id="heading-real-life-analogies"><strong>Real-Life Analogies:</strong></h2>
<h3 id="heading-music-streaming-service"><strong>Music Streaming Service</strong></h3>
<p>Rather than <strong>loading ALL songs into memory</strong>, a streaming service <strong>fetches one song at a time</strong> dynamically.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">music_stream</span>():</span>
    songs = [<span class="hljs-string">"Song 1"</span>, <span class="hljs-string">"Song 2"</span>, <span class="hljs-string">"Song 3"</span>]
    <span class="hljs-keyword">for</span> song <span class="hljs-keyword">in</span> songs:
        <span class="hljs-keyword">yield</span> song

player = music_stream()
print(next(player))  <span class="hljs-comment"># Plays Song 1</span>
print(next(player))  <span class="hljs-comment"># Plays Song 2</span>
</code></pre>
<h3 id="heading-live-weather-updates"><strong>Live Weather Updates</strong></h3>
<p>Weather apps <strong>provide dynamic updates</strong> instead of storing data upfront.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">weather_updates</span>():</span>
    conditions = [<span class="hljs-string">"Sunny"</span>, <span class="hljs-string">"Cloudy"</span>, <span class="hljs-string">"Rainy"</span>]
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">yield</span> random.choice(conditions)

updates = weather_updates()
print(next(updates))  <span class="hljs-comment"># Fetches latest weather update</span>
</code></pre>
<hr />
<h2 id="heading-best-practices-for-context-managers"><strong>Best Practices for Context Managers</strong></h2>
<p><strong>Use context managers</strong> for operations involving resource management.<br /><strong>Prefer</strong> <code>contextlib.contextmanager</code> for simple cases.<br /><strong>Return values from</strong> <code>__enter__()</code> if needed.<br /><strong>Properly handle exceptions</strong> in <code>__exit__()</code>.<br /><strong>Ensure reliable cleanup</strong> regardless of exceptions.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Definition</strong></td><td>Mechanism to manage resources efficiently</td></tr>
<tr>
<td><strong>Keyword</strong></td><td><code>with</code></td></tr>
<tr>
<td><strong>Methods</strong></td><td><code>__enter__()</code>, <code>__exit__()</code></td></tr>
<tr>
<td><strong>Built-in Examples</strong></td><td><code>open()</code>, <code>threading.Lock()</code>, <code>decimal.localcontext()</code></td></tr>
<tr>
<td><strong>Custom Implementation</strong></td><td>Class-based or <code>contextlib.contextmanager</code></td></tr>
<tr>
<td><strong>Exception Handling</strong></td><td>Done in <code>__exit__()</code></td></tr>
<tr>
<td><strong>Use Cases</strong></td><td>Files, databases, sockets, threading</td></tr>
</tbody>
</table>
</div><h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Context Managers are a <strong>clean, reliable, and efficient way</strong> to manage resources. Whether you're dealing with <strong>files, network connections, or databases</strong>, context managers <strong>ensure proper setup and cleanup</strong>, preventing subtle bugs and memory leaks.</p>
<p><strong>Start using Context Managers</strong> in your Python projects to write <strong>robust, maintainable code</strong>!</p>
]]></content:encoded></item><item><title><![CDATA[Generators in Python: A Complete Guide]]></title><description><![CDATA[Introduction to Generators

Generators in Python are a special type of iterable that allow lazy evaluation, meaning they generate values one at a time instead of storing them all in memory at once. They are useful for handling large datasets, optimiz...]]></description><link>https://blog.naveenpn.com/generators-in-python-a-complete-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/generators-in-python-a-complete-guide</guid><category><![CDATA[#Python #PythonGenerators #LazyEvaluation #MemoryOptimization #PythonTips #CodingBestPractices #PythonDevelopers #AdvancedPython #100DaysOfCode #CleanCode #PythonProgramming #LearnPython #SoftwareEngineering #GeneratorsVsLists #InfiniteGenerators #StreamingData #DataProcessing #TechTips #DevCommunity #FibonacciInPython]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Mon, 05 May 2025 09:27:40 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction-to-generators"><strong>Introduction to Generators</strong></h2>
<blockquote>
<p>Generators in Python are a special type of iterable that allow <strong>lazy evaluation</strong>, meaning they generate values one at a time <strong>instead of storing them all in memory at once</strong>. They are useful for handling large datasets, optimizing memory usage, and improving performance in scenarios where iterating over huge amounts of data is required.</p>
</blockquote>
<h2 id="heading-why-use-generators"><strong>Why Use Generators?</strong></h2>
<ul>
<li><p><strong>Improves Memory Efficiency:</strong> Unlike lists, generators do not store all values in memory.</p>
</li>
<li><p><strong>Faster Execution:</strong> Values are generated as needed, reducing unnecessary processing.</p>
</li>
<li><p><strong>Supports Infinite Sequences:</strong> You can define generators that run indefinitely.</p>
</li>
<li><p><strong>Simplifies Complex Iteration Logic:</strong> Avoids using multiple temporary variables.</p>
</li>
</ul>
<hr />
<h2 id="heading-creating-a-basic-generator"><strong>Creating a Basic Generator</strong></h2>
<p>A <strong>generator function</strong> uses the <code>yield</code> keyword to return values <strong>lazily</strong>.</p>
<h3 id="heading-example-1-simple-generator"><strong>Example 1: Simple Generator</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">simple_generator</span>():</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-number">1</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-number">2</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-number">3</span>

gen = simple_generator()

print(next(gen))  <span class="hljs-comment"># Output: 1</span>
print(next(gen))  <span class="hljs-comment"># Output: 2</span>
print(next(gen))  <span class="hljs-comment"># Output: 3</span>
</code></pre>
<h3 id="heading-how-it-works"><strong>How It Works</strong></h3>
<ul>
<li><p>The function <code>simple_generator()</code> does <strong>not</strong> return all values at once.</p>
</li>
<li><p>It <strong>pauses execution</strong> at each <code>yield</code> and resumes when <code>next()</code> is called.</p>
</li>
<li><p>Once all values are yielded, further <code>next()</code> calls raise <code>StopIteration</code>.</p>
</li>
</ul>
<h2 id="heading-iterating-over-a-generator-using-for-loop"><strong>Iterating Over a Generator Using</strong> <code>for</code> Loop</h2>
<p>A generator can be <strong>iterated over</strong> using a <code>for</code> loop:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">number_generator</span>():</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):
        <span class="hljs-keyword">yield</span> i

<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> number_generator():
    print(num)
</code></pre>
<h3 id="heading-output"><strong>Output</strong></h3>
<pre><code class="lang-plaintext">0
1
2
3
4
</code></pre>
<p>This avoids calling <code>next()</code> manually and ensures graceful handling of <code>StopIteration</code>.</p>
<h2 id="heading-generator-expressions"><strong>Generator Expressions</strong></h2>
<p>Generators can be created using <strong>generator expressions</strong>, similar to list comprehensions.</p>
<pre><code class="lang-python">gen_exp = (x * x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>))

print(next(gen_exp))  <span class="hljs-comment"># Output: 0</span>
print(next(gen_exp))  <span class="hljs-comment"># Output: 1</span>
print(next(gen_exp))  <span class="hljs-comment"># Output: 4</span>
</code></pre>
<p>This is <strong>more memory-efficient</strong> than list comprehensions (<code>[x * x for x in range(5)]</code>), which store all values in memory.</p>
<h2 id="heading-generators-vs-lists-memory-usage"><strong>Generators vs Lists (Memory Usage)</strong></h2>
<p>Consider generating <strong>1 million numbers</strong>:</p>
<h3 id="heading-using-lists-consumes-more-memory"><strong>Using Lists (Consumes More Memory)</strong></h3>
<pre><code class="lang-python">nums_list = [x * x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">1000000</span>)]
</code></pre>
<h3 id="heading-using-generators-efficient-memory-usage"><strong>Using Generators (Efficient Memory Usage)</strong></h3>
<pre><code class="lang-python">nums_gen = (x * x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">1000000</span>))
</code></pre>
<ul>
<li><p>Lists store <strong>all values</strong> in memory upfront.</p>
</li>
<li><p>Generators <strong>compute values only when needed</strong>, reducing memory footprint.</p>
</li>
</ul>
<h2 id="heading-generators-for-infinite-sequences"><strong>Generators for Infinite Sequences</strong></h2>
<p>Generators can be used to create <strong>infinite sequences</strong>:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">infinite_counter</span>():</span>
    num = <span class="hljs-number">0</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">yield</span> num
        num += <span class="hljs-number">1</span>

counter = infinite_counter()

print(next(counter))  <span class="hljs-comment"># Output: 0</span>
print(next(counter))  <span class="hljs-comment"># Output: 1</span>
print(next(counter))  <span class="hljs-comment"># Output: 2</span>
</code></pre>
<p>This is ideal for streaming data, real-time processing, or dynamically generating content.</p>
<h2 id="heading-using-yield-with-send"><strong>Using</strong> <code>yield</code> with <code>send()</code></h2>
<p>Generators can receive values using the <code>send()</code> method.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greeter</span>():</span>
    name = <span class="hljs-keyword">yield</span> <span class="hljs-string">"Enter your name:"</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>

g = greeter()
print(next(g))       <span class="hljs-comment"># Output: Enter your name:</span>
print(g.send(<span class="hljs-string">"Rahul"</span>))  <span class="hljs-comment"># Output: Hello, Rahul!</span>
</code></pre>
<ul>
<li><p><code>next()</code> starts the generator.</p>
</li>
<li><p><code>send()</code> sends a value to the <code>yield</code> expression.</p>
</li>
</ul>
<h2 id="heading-using-yield-from-delegating-iteration"><strong>Using</strong> <code>yield from</code> (Delegating Iteration)</h2>
<p>To <strong>yield values from another iterable</strong>, use <code>yield from</code>:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sub_generator</span>():</span>
    <span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> [<span class="hljs-number">10</span>, <span class="hljs-number">20</span>, <span class="hljs-number">30</span>]

<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> sub_generator():
    print(num)
</code></pre>
<h3 id="heading-output-1"><strong>Output</strong></h3>
<pre><code class="lang-plaintext">10
20
30
</code></pre>
<p>This is cleaner than looping through another iterable manually.</p>
<h2 id="heading-real-world-applications-of-generators"><strong>Real-World Applications of Generators</strong></h2>
<h3 id="heading-1-processing-large-files-without-loading-into-memory"><strong>1. Processing Large Files Without Loading into Memory</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_large_file</span>(<span class="hljs-params">file_path</span>):</span>
    <span class="hljs-keyword">with</span> open(file_path, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
        <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> file:
            <span class="hljs-keyword">yield</span> line

<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> read_large_file(<span class="hljs-string">"data.txt"</span>):
    print(line)
</code></pre>
<ul>
<li>Processes <strong>huge files efficiently</strong> without reading the entire file at once.</li>
</ul>
<h3 id="heading-2-streaming-live-sensor-data"><strong>2. Streaming Live Sensor Data</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sensor_stream</span>():</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">yield</span> random.uniform(<span class="hljs-number">20</span>, <span class="hljs-number">30</span>)  <span class="hljs-comment"># Simulating temperature sensor</span>
        time.sleep(<span class="hljs-number">1</span>)  <span class="hljs-comment"># Wait for next reading</span>

sensor = sensor_stream()

<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):  
    print(next(sensor))
</code></pre>
<ul>
<li>Continuously <strong>streams live data</strong> without storing previous values.</li>
</ul>
<h3 id="heading-3-generating-fibonacci-sequence"><strong>3. Generating Fibonacci Sequence</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fibonacci</span>():</span>
    a, b = <span class="hljs-number">0</span>, <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">yield</span> a
        a, b = b, a + b

fib_gen = fibonacci()

<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):  
    print(next(fib_gen))
</code></pre>
<ul>
<li>Generates Fibonacci numbers <strong>without storing</strong> previous values.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Decorators in Python: A Complete Guide]]></title><description><![CDATA[Introduction to Decorators

Decorators in Python are a powerful tool that allows modifying or extending the behavior of functions without altering their actual implementation. They make code more readable, reusable, and maintainable by allowing modif...]]></description><link>https://blog.naveenpn.com/decorators-in-python-a-complete-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/decorators-in-python-a-complete-guide</guid><category><![CDATA[ #PythonDecorators ]]></category><category><![CDATA[ #AdvancedPython]]></category><category><![CDATA[Python]]></category><category><![CDATA[coding tips]]></category><category><![CDATA[hire python developers]]></category><category><![CDATA[clean code]]></category><category><![CDATA[code optimization]]></category><category><![CDATA[python tips]]></category><category><![CDATA[Python community]]></category><category><![CDATA[DevLife]]></category><category><![CDATA[debugging tips]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Mon, 05 May 2025 09:23:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752853617438/9575dac4-dfc3-4217-9ac3-a8bcc7152918.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction-to-decorators"><strong>Introduction to Decorators</strong></h2>
<blockquote>
<p>Decorators in Python are a powerful tool that allows <strong>modifying or extending the behavior of functions</strong> without altering their actual implementation. They make code more <strong>readable, reusable, and maintainable</strong> by allowing modifications to functions in a clean and efficient way.</p>
</blockquote>
<h2 id="heading-why-use-decorators"><strong>Why Use Decorators?</strong></h2>
<ul>
<li><p><strong>Code Reusability:</strong> Avoid repeating code for similar functionalities.</p>
</li>
<li><p><strong>Separation of Concerns:</strong> Keeps function logic independent of additional behavior.</p>
</li>
<li><p><strong>Enhanced Readability:</strong> Makes functions cleaner by abstracting modifications.</p>
</li>
<li><p><strong>Useful for Logging, Authentication, Timing Functions, and More.</strong></p>
</li>
</ul>
<h2 id="heading-basic-syntax-of-a-decorator"><strong>Basic Syntax of a Decorator</strong></h2>
<p>A <strong>decorator</strong> is a function that takes another function as input and extends its behavior.</p>
<h3 id="heading-step-1-creating-a-basic-decorator"><strong>Step 1: Creating a Basic Decorator</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>():</span>
        print(<span class="hljs-string">"Something before the function runs."</span>)
        func()
        print(<span class="hljs-string">"Something after the function runs."</span>)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@my_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">say_hello</span>():</span>
    print(<span class="hljs-string">"Hello, World!"</span>)

say_hello()
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">Something before the function runs.
Hello, World!
Something after the function runs.
</code></pre>
<h3 id="heading-how-it-works"><strong>How It Works</strong></h3>
<ul>
<li><p><code>my_decorator(func)</code> receives the function <code>say_hello()</code>.</p>
</li>
<li><p><code>wrapper()</code> adds additional behavior before and after calling <code>func()</code>.</p>
</li>
<li><p><code>@my_decorator</code> applies the decorator to <code>say_hello()</code>, modifying its behavior.</p>
</li>
</ul>
<h2 id="heading-decorators-with-arguments"><strong>Decorators with Arguments</strong></h2>
<p>If the decorated function takes arguments, use <code>*args</code> and <code>**kwargs</code> inside the wrapper.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">smart_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">"Executing decorated function..."</span>)
        result = func(*args, **kwargs)
        print(<span class="hljs-string">"Finished execution."</span>)
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@smart_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-keyword">return</span> a + b

print(add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>))
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">Executing decorated function...
Finished execution.
8
</code></pre>
<h2 id="heading-built-in-decorators-in-python"><strong>Built-in Decorators in Python</strong></h2>
<p>Python provides several built-in decorators, commonly used for modifying methods in classes.</p>
<h3 id="heading-1-staticmethod"><strong>1.</strong> <code>@staticmethod</code></h3>
<p>Defines a function inside a class that doesn’t require access to instance attributes.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MathOperations</span>:</span>
<span class="hljs-meta">    @staticmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">a, b</span>):</span>
        <span class="hljs-keyword">return</span> a + b

print(MathOperations.add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>))  <span class="hljs-comment"># Output: 8</span>
</code></pre>
<h3 id="heading-2-classmethod"><strong>2.</strong> <code>@classmethod</code></h3>
<p>Allows methods to receive the class itself (<code>cls</code>) instead of instance (<code>self</code>).</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span>
    class_var = <span class="hljs-string">"Hello"</span>

<span class="hljs-meta">    @classmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">show_class_var</span>(<span class="hljs-params">cls</span>):</span>
        <span class="hljs-keyword">return</span> cls.class_var

print(MyClass.show_class_var())  <span class="hljs-comment"># Output: Hello</span>
</code></pre>
<h3 id="heading-3-property"><strong>3.</strong> <code>@property</code></h3>
<p>Used to define <strong>read-only properties</strong> in a class.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name</span>):</span>
        self._name = name

<span class="hljs-meta">    @property</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">name</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self._name

p = Person(<span class="hljs-string">"Mahesh"</span>)
print(p.name)  <span class="hljs-comment"># Output: Mahesh</span>
</code></pre>
<h2 id="heading-using-multiple-decorators"><strong>Using Multiple Decorators</strong></h2>
<p>You can stack multiple decorators on a single function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator1</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>():</span>
        print(<span class="hljs-string">"Decorator 1 before function"</span>)
        func()
        print(<span class="hljs-string">"Decorator 1 after function"</span>)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator2</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>():</span>
        print(<span class="hljs-string">"Decorator 2 before function"</span>)
        func()
        print(<span class="hljs-string">"Decorator 2 after function"</span>)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@decorator1</span>
<span class="hljs-meta">@decorator2</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>():</span>
    print(<span class="hljs-string">"Hello, World!"</span>)

hello()
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">Decorator 1 before function
Decorator 2 before function
Hello, World!
Decorator 2 after function
Decorator 1 after function
</code></pre>
<h2 id="heading-real-world-applications-of-decorators"><strong>Real-World Applications of Decorators</strong></h2>
<h3 id="heading-1-logging-function-execution"><strong>1. Logging Function Execution</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">f"Executing <span class="hljs-subst">{func.__name__}</span> at <span class="hljs-subst">{time.strftime(<span class="hljs-string">'%X'</span>)}</span>"</span>)
        <span class="hljs-keyword">return</span> func(*args, **kwargs)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@log_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>):</span>
    print(<span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>)

greet(<span class="hljs-string">"Mahesh"</span>)
</code></pre>
<h3 id="heading-2-checking-user-authentication"><strong>2. Checking User Authentication</strong></h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">requires_authentication</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">user, *args, **kwargs</span>):</span>
        <span class="hljs-keyword">if</span> user == <span class="hljs-string">"admin"</span>:
            <span class="hljs-keyword">return</span> func(*args, **kwargs)
        <span class="hljs-keyword">else</span>:
            print(<span class="hljs-string">"Access Denied"</span>)
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@requires_authentication</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">secure_action</span>():</span>
    print(<span class="hljs-string">"Performing secure action..."</span>)

secure_action(<span class="hljs-string">"user"</span>)   <span class="hljs-comment"># Output: Access Denied</span>
secure_action(<span class="hljs-string">"admin"</span>)  <span class="hljs-comment"># Output: Performing secure action...</span>
</code></pre>
<h3 id="heading-3-timing-function-execution"><strong>3. Timing Function Execution</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">timer_decorator</span>(<span class="hljs-params">func</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(<span class="hljs-string">f"<span class="hljs-subst">{func.__name__}</span> took <span class="hljs-subst">{end_time - start_time:<span class="hljs-number">.4</span>f}</span> seconds"</span>)
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@timer_decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">slow_function</span>():</span>
    time.sleep(<span class="hljs-number">2</span>)
    print(<span class="hljs-string">"Finished processing."</span>)

slow_function()
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-plaintext">Finished processing.
slow_function took 2.0001 seconds
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Logging in Python: A Comprehensive Guide]]></title><description><![CDATA[Introduction to Logging

Logging is a crucial aspect of software development that helps developers track events, debug issues, and monitor application behavior. Instead of using print() statements for debugging, Python's logging module provides a str...]]></description><link>https://blog.naveenpn.com/logging-in-python-a-comprehensive-guide</link><guid isPermaLink="true">https://blog.naveenpn.com/logging-in-python-a-comprehensive-guide</guid><category><![CDATA[#PythonLogging]]></category><category><![CDATA[#LoggingInPython ]]></category><category><![CDATA[Python]]></category><category><![CDATA[loggingmodule]]></category><category><![CDATA[python tips]]></category><category><![CDATA[software development]]></category><category><![CDATA[debugging]]></category><category><![CDATA[clean code]]></category><category><![CDATA[#DevOps #DevOpsRoadmap #ContinuousIntegration #ContinuousDelivery #Agile #Automation #IaC #InfrastructureAsCode #Docker #Kubernetes #CloudComputing #AWS #Azure #GCP #Monitoring #Logging #BestPractices #Collaboration  #SoftwareDevelopment #Programming]]></category><category><![CDATA[hire python developers]]></category><category><![CDATA[PythonForBeginners]]></category><dc:creator><![CDATA[Naveen Pn]]></dc:creator><pubDate>Mon, 05 May 2025 09:15:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752853242455/52887e89-a3f6-4ae5-a010-a8bc552d3fc9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction-to-logging"><strong>Introduction to Logging</strong></h2>
<blockquote>
<p>Logging is a crucial aspect of software development that helps developers <strong>track events, debug issues, and monitor application behavior</strong>. Instead of using <code>print()</code> statements for debugging, Python's <strong>logging module</strong> provides a <strong>structured, efficient, and flexible</strong> way to record messages.</p>
</blockquote>
<h3 id="heading-why-use-logging-instead-of-print"><strong>Why Use Logging Instead of</strong> <code>print()</code>?</h3>
<ol>
<li><p><strong>Severity Levels:</strong> Logs allow categorizing messages into different levels (INFO, WARNING, ERROR, etc.).</p>
</li>
<li><p><strong>Better Debugging:</strong> Logs persist even after execution, unlike <code>print()</code>, which disappears.</p>
</li>
<li><p><strong>Custom Formatting:</strong> Logging provides timestamps, log levels, and message customization.</p>
</li>
<li><p><strong>Multiple Output Streams:</strong> Logs can be stored in files, databases, or external monitoring services.</p>
</li>
</ol>
<h2 id="heading-basic-logging-in-python"><strong>Basic Logging in Python</strong></h2>
<p>Python provides a built-in <code>logging</code> module that allows different log levels:</p>
<h3 id="heading-1-importing-the-logging-module"><strong>1. Importing the</strong> <code>logging</code> Module</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
</code></pre>
<h3 id="heading-2-setting-up-basic-logging-configuration"><strong>2. Setting Up Basic Logging Configuration</strong></h3>
<pre><code class="lang-python">logging.basicConfig(level=logging.INFO)  <span class="hljs-comment"># Set log level to INFO</span>
logging.info(<span class="hljs-string">"This is an INFO message"</span>)  <span class="hljs-comment"># Output: INFO:root:This is an INFO message</span>
</code></pre>
<h3 id="heading-3-logging-different-levels"><strong>3. Logging Different Levels</strong></h3>
<p>Python defines multiple logging levels:</p>
<pre><code class="lang-python">logging.debug(<span class="hljs-string">"Debugging details"</span>)    <span class="hljs-comment"># Used for debugging information</span>
logging.info(<span class="hljs-string">"General information"</span>)   <span class="hljs-comment"># Used for informational messages</span>
logging.warning(<span class="hljs-string">"Something looks off"</span>) <span class="hljs-comment"># Used for warnings</span>
logging.error(<span class="hljs-string">"An error occurred"</span>)    <span class="hljs-comment"># Used for error reporting</span>
logging.critical(<span class="hljs-string">"System failure!"</span>)   <span class="hljs-comment"># Used for serious failures</span>
</code></pre>
<h3 id="heading-4-custom-log-formatting"><strong>4. Custom Log Formatting</strong></h3>
<p>Customizing logs with <strong>timestamp, level, and message format</strong>:</p>
<pre><code class="lang-python">logging.basicConfig(
    format=<span class="hljs-string">"%(asctime)s - %(levelname)s - %(message)s"</span>,
    level=logging.INFO
)
logging.info(<span class="hljs-string">"Custom formatted log message"</span>)
</code></pre>
<p><strong>Example Output:</strong></p>
<pre><code class="lang-plaintext">2025-05-05 12:45:30 - INFO - Custom formatted log message
</code></pre>
<h2 id="heading-writing-logs-to-a-file"><strong>Writing Logs to a File</strong></h2>
<p>Instead of displaying logs in the console, logs can be stored in a file:</p>
<pre><code class="lang-python">logging.basicConfig(
    filename=<span class="hljs-string">"app.log"</span>,
    format=<span class="hljs-string">"%(asctime)s - %(levelname)s - %(message)s"</span>,
    level=logging.INFO
)

logging.info(<span class="hljs-string">"This log is saved in a file!"</span>)
</code></pre>
<p>The log will be written to <strong>app.log</strong>.</p>
<h2 id="heading-using-loggers-for-modular-logging"><strong>Using Loggers for Modular Logging</strong></h2>
<h3 id="heading-creating-a-custom-logger"><strong>Creating a Custom Logger</strong></h3>
<pre><code class="lang-python">logger = logging.getLogger(<span class="hljs-string">"custom_logger"</span>)  <span class="hljs-comment"># Create a named logger</span>
logger.setLevel(logging.DEBUG)

<span class="hljs-comment"># Create a handler for logging to a file</span>
file_handler = logging.FileHandler(<span class="hljs-string">"custom.log"</span>)
formatter = logging.Formatter(<span class="hljs-string">"%(asctime)s - %(name)s - %(levelname)s - %(message)s"</span>)

file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

logger.debug(<span class="hljs-string">"This debug log is recorded in custom.log"</span>)
</code></pre>
<p>This method ensures modular logging across different parts of a program.</p>
<h2 id="heading-using-logging-in-a-real-world-application"><strong>Using Logging in a Real-World Application</strong></h2>
<h3 id="heading-example-api-request-logging"><strong>Example: API Request Logging</strong></h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">import</span> requests

logging.basicConfig(format=<span class="hljs-string">"%(asctime)s - %(levelname)s - %(message)s"</span>, level=logging.INFO)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_data</span>(<span class="hljs-params">url</span>):</span>
    logging.info(<span class="hljs-string">f"Fetching data from <span class="hljs-subst">{url}</span>"</span>)
    <span class="hljs-keyword">try</span>:
        response = requests.get(url)
        response.raise_for_status()  <span class="hljs-comment"># Raise error for failed requests</span>
        logging.info(<span class="hljs-string">f"Received response: <span class="hljs-subst">{response.status_code}</span>"</span>)
        <span class="hljs-keyword">return</span> response.json()
    <span class="hljs-keyword">except</span> requests.exceptions.RequestException <span class="hljs-keyword">as</span> e:
        logging.error(<span class="hljs-string">f"Request failed: <span class="hljs-subst">{e}</span>"</span>)

data = fetch_data(<span class="hljs-string">"https://api.github.com"</span>)
</code></pre>
<h3 id="heading-example-output"><strong>Example Output</strong></h3>
<pre><code class="lang-plaintext">2025-05-05 12:50:15 - INFO - Fetching data from https://api.github.com
2025-05-05 12:50:15 - INFO - Received response: 200
</code></pre>
]]></content:encoded></item></channel></rss>