<?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[Python Programming Tutorials and Articles - GeekPython]]></title><description><![CDATA[Get access to some cool tutorials and astounding facts about Python Programming. Python tutorials, articles and projects for developers for all skill levels.]]></description><link>https://teamgeek.geekpython.in</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1691855889454/7gEWOLRAv.png</url><title>Python Programming Tutorials and Articles - GeekPython</title><link>https://teamgeek.geekpython.in</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 20:47:52 GMT</lastBuildDate><atom:link href="https://teamgeek.geekpython.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Power-up API Testing with EchoAPI's AI]]></title><description><![CDATA[When you’re building an application, one thing you can’t skip is API testing. Whether it’s a login flow, payment gateway, or a complex e-commerce workflow, ensuring your APIs behave correctly saves you from nasty surprises in production.
I had alread...]]></description><link>https://teamgeek.geekpython.in/power-up-api-testing-with-echoapis-ai</link><guid isPermaLink="true">https://teamgeek.geekpython.in/power-up-api-testing-with-echoapis-ai</guid><category><![CDATA[APIs]]></category><category><![CDATA[api]]></category><category><![CDATA[AI]]></category><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 25 Sep 2025 16:24:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758478331138/95bb8615-c3d8-4e77-8fa0-207978b62d3d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you’re building an application, one thing you can’t skip is <strong>API testing</strong>. Whether it’s a login flow, payment gateway, or a complex e-commerce workflow, ensuring your APIs behave correctly saves you from nasty surprises in production.</p>
<p>I had already explored <strong>EchoAPI</strong> earlier, but while working on my recent project, I revisited it. And guess what? They’ve supercharged it with <strong>AI-powered features</strong>.</p>
<p>This update caught my attention immediately:</p>
<ul>
<li><p>✅ <strong>One-click Docs</strong></p>
</li>
<li><p>✅ <strong>Fake data generator</strong></p>
</li>
<li><p>✅ <strong>Bulk parameter updates</strong></p>
</li>
<li><p>✅ <strong>AI Convert</strong></p>
</li>
<li><p>✅ <strong>AI Test-case generator</strong></p>
</li>
<li><p>✅ <strong>AI-powered script &amp; assertion generator</strong></p>
</li>
</ul>
<p>In this blog, I’ll take you through my full experience, step by step, so you’ll know exactly how these features can save you <strong>hours of manual testing</strong>.</p>
<hr />
<h2 id="heading-installing-and-setting-up-echoapi">Installing and Setting Up EchoAPI</h2>
<p>Before we dive into the AI features, let’s start with the basics.</p>
<p>I downloaded and installed <a target="_blank" href="https://www.echoapi.com/download"><strong>EchoAPI’s desktop app</strong></a>. The interface is clean and very intuitive, something between Postman and Insomnia, but with its own unique <strong>AI touch</strong>.</p>
<p>For this demo, I connected my <strong>FastAPI e-commerce backend</strong>. This app has typical endpoints like:</p>
<ul>
<li><p><code>POST /signup</code></p>
</li>
<li><p><code>POST /login</code></p>
</li>
<li><p><code>GET/cart</code></p>
</li>
<li><p><code>POST /cart/add</code></p>
</li>
<li><p><code>POST /order/place</code></p>
</li>
<li><p><code>POST /payment</code></p>
</li>
<li><p><code>GET/products</code></p>
</li>
<li><p><code>GET/products/{product_id}</code></p>
</li>
</ul>
<p>Perfect playground to test EchoAPI’s AI magic.</p>
<hr />
<h2 id="heading-ai-generated-test-cases">AI-Generated Test Cases</h2>
<p>Let’s start with the <strong>AI Test-case Generator</strong>.</p>
<p>Normally, writing test cases for each endpoint is a tedious process:</p>
<ul>
<li><p>You have to decide scenarios.</p>
</li>
<li><p>Write expected outcomes.</p>
</li>
<li><p>Prepare data for each run.</p>
</li>
<li><p>And then execute them manually.</p>
</li>
</ul>
<p>But EchoAPI just makes it <strong>one-click</strong>.</p>
<h3 id="heading-step-1-pick-an-endpoint">Step 1: Pick an Endpoint</h3>
<p>Inside EchoAPI, I selected an endpoint from my FastAPI project. Let’s say the <code>signup</code> endpoint.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758383102687/409523b1-9794-45a5-8bd0-5a7edc5abd4c.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-2-go-to-the-cases-section">Step 2: Go to the Cases Section</h3>
<p>Here, EchoAPI shows <strong>8 standard testing dimensions</strong> (like API Specification Compliance Tests, Invalid Input Handling Tests, HTTP Method Validation, etc.). I kept all of them selected.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758383431531/b7e1e8f9-aace-445e-b43e-9ca69d339092.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-3-generate">Step 3: Generate</h3>
<p>I clicked <strong>Generate</strong>, and instantly, the AI created:</p>
<ul>
<li><ul>
<li><p><strong>Case Objectives</strong> (e.g., “Test signup with valid data”, “Test signup with missing email”)</p>
<p>    * <strong>Expected Outcomes</strong> (e.g., “Should return 200 OK”, “Should return 400 Bad Request”)</p>
<p>    * <strong>Test Data</strong> (realistic values automatically generated)</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758386079904/f98e4489-b4df-48a7-9b7b-bb71a38b0e73.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-4-apply-amp-run">Step 4: Apply &amp; Run</h3>
<p>When I clicked <strong>Apply and Test</strong>, EchoAPI ran <strong>13 cases with 35 different sets of data</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758386301179/2b3c3abf-10a4-486c-9c53-37cbdb4381f0.png" alt class="image--center mx-auto" /></p>
<p>That’s a massive workload handled automatically. Imagine writing these manually; it could easily take a couple of hours per endpoint.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758386620507/7742a1a9-e3b6-435d-b8fd-b1c7e28c7ae9.png" alt class="image--center mx-auto" /></p>
<p>And here’s the best part: if something fails, EchoAPI shows why it <strong>exactly failed</strong>, with every detail in the response section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758386800708/cae09b71-8b06-43ce-9c1d-e56e38c7601e.png" alt class="image--center mx-auto" /></p>
<p><em>Tip: You can re-run failed cases separately to debug faster.</em></p>
<hr />
<h2 id="heading-ai-powered-scripts-amp-assertions">AI-Powered Scripts &amp; Assertions</h2>
<p>Sometimes you need more than automated test cases; you want <strong>custom scripts and validation rules</strong>. EchoAPI covers that too.</p>
<h3 id="heading-ai-script-generator">AI Script Generator</h3>
<p>Let’s say you want a test script for checking a complex payment flow. Instead of writing it yourself, you just ask the AI:</p>
<blockquote>
<p>I typed “Generate a script to test a payment API with both valid and invalid card details.”</p>
</blockquote>
<p>EchoAPI writes it out, and the script is ready to run.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758469919069/11601cba-d660-4075-a2be-b2af265cd486.png" alt class="image--center mx-auto" /></p>
<p><em>You can edit these AI-generated scripts or chain them with your own logic if needed.</em></p>
<h3 id="heading-ai-assertions">AI Assertions</h3>
<p>Assertions are what validate your API’s response. Doing this manually is slow, especially when responses are large.</p>
<p>Example:</p>
<ul>
<li><p>You send a request.</p>
</li>
<li><p>You get a JSON response like the following:</p>
</li>
</ul>
<pre><code class="lang-json">{ <span class="hljs-attr">"status"</span>: <span class="hljs-string">"success"</span>, <span class="hljs-attr">"order_id"</span>: <span class="hljs-string">"12345"</span> }
</code></pre>
<p>Now, instead of manually writing like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">assert</span> response.status == <span class="hljs-string">"success"</span>
<span class="hljs-keyword">assert</span> <span class="hljs-string">"order_id"</span> <span class="hljs-keyword">in</span> response
</code></pre>
<p>You just click <strong>AI Assert</strong> in the <strong>response section</strong>, and EchoAPI generates these checks for you.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758470159691/16025c9c-0b5d-4c41-bfd3-edf4f6cda640.png" alt class="image--center mx-auto" /></p>
<p>Even better, you can <strong>add or modify assertions in plain English</strong>:</p>
<blockquote>
<p>“Assert that the response returns status 201 and user_id should not be empty.”</p>
</blockquote>
<p>And it updates your tests. This makes it super friendly even for non-coders who just want to validate business logic.</p>
<hr />
<h2 id="heading-chaining-multiple-apis">Chaining Multiple APIs</h2>
<p>Real-world apps rarely run on a single endpoint. You usually need a <strong>workflow</strong>: signup → login → add-to-cart → place-order → make-payment.</p>
<p>EchoAPI lets you <strong>chain APIs together</strong> so you can test them all in one flow.</p>
<p>Here’s how I did it:</p>
<h3 id="heading-step-1-create-folder-amp-subfolder">Step 1: Create Folder &amp; Subfolder</h3>
<p>First, go to the <strong>“Tests”</strong> section. Here, I created a folder in EchoAPI for my test flows, then a subfolder for this specific checkout flow.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758470761843/c744d250-07a4-47ab-8e8c-6f2fbfd7b88c.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-2-add-endpoints-by-reference">Step 2: Add Endpoints by Reference</h3>
<p>I selected my endpoints into this folder <strong>by reference</strong> (not by copy). This way, if my endpoint changes, it stays automatically synchronized here.</p>
<h3 id="heading-step-3-configure-each-endpoint">Step 3: Configure Each Endpoint</h3>
<ul>
<li><p><strong>Signup Endpoint</strong>: Entered new user data and saved.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758470982057/e2917ee4-a7f6-4069-84aa-38230a3b2293.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Login Endpoint</strong>: Used the same credentials. This gives me <code>access_token</code>.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758471227799/25843d73-b6f8-4aed-aa08-4866fc9480e1.png" alt class="image--center mx-auto" /></p>
</li>
<li><ul>
<li><p>Captured the <strong>access token</strong> from the response and stored it as a variable using JSONPath expression in the Post-response section.</p>
<ul>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758818188726/b464a8c2-4dc5-41ca-a4cf-76d87ea0d063.png" alt class="image--center mx-auto" /></li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Add-to-Cart Endpoint</strong>: Added a product. Passed the access token in the <code>Auth</code> header.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758474622097/72620123-d5a3-4a12-be5f-b5b2ca24cb28.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Place-Order Endpoint</strong>: Placed the order. Passed the access token in the <code>Auth</code> header. Captured the <strong>order ID</strong> and stored it as a variable in the Post-response section.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758474844158/5f4600d9-b9d2-4aa2-ab29-9fd7f1bedb9f.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Make-Payment Endpoint</strong>: Used the captured order ID and passed the access token in <code>Auth</code> header to complete the payment.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758475065914/9e396492-7503-43fb-9fc2-4fdcc6488cf1.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h3 id="heading-step-4-run-the-flow">Step 4: Run the Flow</h3>
<p>After choosing the preferred environment, I saved everything and ran the whole chain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758475609494/8a1d34fe-0aba-454a-a574-f44c0ab06458.png" alt class="image--center mx-auto" /></p>
<p>Result? EchoAPI executed the flow step by step, showing me <strong>where things passed or failed</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758476189749/6710eda6-ec7d-468f-a83e-5257ec3050ba.png" alt class="image--center mx-auto" /></p>
<p>This is a <strong>game-changer;</strong> instead of manually juggling values between requests, everything flows automatically.</p>
<hr />
<h2 id="heading-echoapi-vs-postman-amp-thunder-client-ai-features-comparison">EchoAPI vs Postman &amp; Thunder Client: AI Features Comparison</h2>
<p>When it comes to developer tools, <strong>positioning matters</strong>, not just what features you have, but how they stand out and why someone should choose your solution over existing ones. Let’s break down how EchoAPI compares with Postman and Thunder Client.</p>
<h3 id="heading-postman-ai-features-amp-strengths">Postman: AI Features &amp; Strengths</h3>
<p>Postman has long been the industry leader for API testing and collaboration, and over time, they’ve been adding AI capabilities. Some highlights include:</p>
<ul>
<li><p><strong>Postbot (AI Assistant):</strong> Helps debug APIs, write tests, and analyze large responses or datasets with ease.</p>
</li>
<li><p><strong>AI Agent Builder:</strong> Lets you build agent-like workflows by combining AI models with APIs. You can design drag-and-drop visual workflows, use templates, and even tap into Postman’s growing network of APIs and MCP servers.</p>
</li>
<li><p><strong>Flows, MCP &amp; AI Developer Tools:</strong> Postman supports experiments with AI models, evaluating multiple LLMs, generating prompts, and building test suites.</p>
</li>
<li><p><strong>Autocomplete, Suggestions &amp; Docs Assistance:</strong> Useful for writing tests, analyzing large responses, and keeping documentation in sync.</p>
</li>
</ul>
<p><strong>Limitations:</strong></p>
<ul>
<li><p>Test-case generation isn’t fully automatic: Postbot can help, but often requires manual tweaking.</p>
</li>
<li><p>Workflows like chaining APIs, extracting variables, or setting up environments still require a lot of manual setup.</p>
</li>
<li><p>Postman’s depth comes with complexity, meaning a steeper learning curve and heavier overhead for new users.</p>
</li>
</ul>
<hr />
<h3 id="heading-thunder-client-ai-features-amp-strengths">Thunder Client: AI Features &amp; Strengths</h3>
<p>Thunder Client takes a different approach: <strong>lightweight API testing inside VS Code</strong>. Its philosophy is simplicity and speed.</p>
<ul>
<li><p><strong>Scriptless Testing &amp; GUI Assertions:</strong> Instead of writing code, you can define tests via dropdowns and GUI selectors (e.g., status codes, response fields).</p>
</li>
<li><p><strong>Core Features:</strong> Collections, environments, request history, and local storage — all the basics you need for quick API testing.</p>
</li>
<li><p><strong>AI Integration (Early Stages):</strong> Thunder Client has announced AI-generated tests as <strong>“coming soon”</strong>, meaning their AI feature set is still developing.</p>
</li>
<li><p><strong>CI/CD &amp; Git Sync:</strong> Useful for teams to collaborate, share collections, and integrate tests into workflows.</p>
</li>
</ul>
<p><strong>Limitations:</strong></p>
<ul>
<li><p>AI support is limited and still maturing.</p>
</li>
<li><p>Not ideal for complex workflows like chained requests or dynamic variable management.</p>
</li>
<li><p>Lacks no-code flow builders or advanced automation beyond simple assertions.</p>
</li>
</ul>
<h3 id="heading-echoapis-edge">EchoAPI’s Edge</h3>
<p>Here’s where <strong>EchoAPI differentiates itself</strong>: AI isn’t just an add-on; it’s the <strong>engine</strong> of the testing workflow.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature / Area</td><td>EchoAPI Strength</td><td>Why It Matters vs Postman / Thunder Client</td></tr>
</thead>
<tbody>
<tr>
<td><strong>AI Test-Case Generation</strong></td><td>Generates full test suites with objectives, expected outcomes, and realistic data in one click.</td><td>Postman’s Postbot assists but often requires manual edits; Thunder Client’s AI is still “coming soon.”</td></tr>
<tr>
<td><strong>AI Scripts &amp; Assertions</strong></td><td>Creates complete test scripts and assertions from plain English, automatically extracting variables.</td><td>Postman offers partial assistance; Thunder Client supports only basic GUI assertions.</td></tr>
<tr>
<td><strong>Chained API Flows</strong></td><td>Seamlessly chains endpoints, passes tokens/IDs automatically, and keeps endpoints synced by reference.</td><td>Postman supports flows, but setup is heavier; Thunder Client focuses more on single requests.</td></tr>
<tr>
<td><strong>User-Friendly for Non-Coders</strong></td><td>Natural-language assertions, one-click test generation, and easy debugging.</td><td>Postman is powerful but complex; Thunder Client is simple but lacks advanced AI automation.</td></tr>
<tr>
<td><strong>Speed &amp; Productivity</strong></td><td>High automation cuts hours of work into minutes.</td><td>Postman is slower for setup-heavy workflows; Thunder Client is fast but limited to simple tasks.</td></tr>
</tbody>
</table>
</div><h3 id="heading-at-a-glance">At a Glance</h3>
<ul>
<li><p><strong>Postman</strong>: Best for power users who want deep control, integrations, and community-driven workflows.</p>
</li>
<li><p><strong>Thunder Client</strong>: Great for developers who prefer simplicity, speed, and testing inside VS Code.</p>
</li>
<li><p><strong>EchoAPI</strong>: Combines the best of both worlds: advanced AI automation, full workflow chaining, variable management, and a friendly UI that works for both coders and non-coders.</p>
</li>
</ul>
<hr />
<h3 id="heading-why-this-comparison-matters">Why This Comparison Matters</h3>
<p>There are plenty of API tools out there. But the <strong>real value</strong> is in how much time you save, how many bugs you prevent, and how easily your team can scale test coverage.</p>
<ul>
<li><p>If you’re working on a big codebase, managing dozens of endpoints, or testing chained workflows, EchoAPI gives you automation that cuts down boilerplate and speeds up debugging.</p>
</li>
<li><p>If you’re working on a small project, Thunder Client might be enough for its simplicity. If you want the biggest ecosystem and integrations, Postman is still a solid choice.</p>
</li>
<li><p>But if you want <strong>AI-native testing</strong> that actually handles the heavy lifting, EchoAPI offers a strong alternative; one that’s already delivering mature, practical automation today.</p>
</li>
</ul>
<h2 id="heading-why-this-matters">Why This Matters</h2>
<p>EchoAPI’s AI features literally <strong>compress hours of manual work into seconds</strong>.</p>
<ul>
<li><p><strong>AI Test-case generator</strong>: No need to brainstorm test cases.</p>
</li>
<li><p><strong>AI Scripts</strong>: No need to code repetitive test scripts.</p>
</li>
<li><p><strong>AI Assertions</strong>: Validation without writing manual checks.</p>
</li>
<li><p><strong>Chained APIs</strong>: End-to-end workflow testing in one go.</p>
</li>
</ul>
<p>For <strong>developers</strong>, it means faster testing and less frustration. For <strong>QA engineers</strong>, it means scaling test coverage without extra effort. For <strong>teams</strong>, it means fewer bugs slip into production.</p>
<hr />
<h2 id="heading-results-summary">Results Summary</h2>
<p>After spending time with EchoAPI’s AI-powered tools, here’s my honest takeaway:</p>
<ul>
<li><p>The <strong>auto test-case generation</strong> is the highlight; it gives you complete coverage in seconds.</p>
</li>
<li><p>The <strong>AI script &amp; assertion generator</strong> saves tons of time when building complex validations.</p>
</li>
<li><p>The <strong>multi-API chaining</strong> feels like real-world automation without the complexity of writing a giant test framework yourself.</p>
</li>
</ul>
<hr />
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>EchoAPI with AI isn’t just another API client. It’s like having a <strong>QA assistant</strong> sitting beside you.</p>
<p>Instead of writing, organizing, and debugging everything manually, you just <strong>guide the AI</strong> and let it handle the heavy lifting.</p>
<hr />
<p><em>That’s my full walkthrough of EchoAPI’s AI features. Have you tried AI-assisted testing yet?</em></p>
<hr />
<p><strong>That’s it for now…</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[How to Install PyPy and Use it?]]></title><description><![CDATA[PyPy is an implementation of Python written in RPython (Reduced Python) language, and it is seen as a replacement for CPython.
PyPy claims that it is almost a drop-in replacement for CPython and can beat it on speed and memory usage. It supports libr...]]></description><link>https://teamgeek.geekpython.in/how-to-install-pypy-and-use-it</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-install-pypy-and-use-it</guid><category><![CDATA[pypy]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Mon, 06 Jan 2025 14:13:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736169660766/f67271f3-4faa-42fc-bf97-5b2fc029e60e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>PyPy</strong> is an implementation of Python written in <strong>RPython</strong> (Reduced Python) language, and it is seen as a replacement for CPython.</p>
<p>PyPy claims that it is almost a drop-in replacement for CPython and can beat it on speed and memory usage. It supports libraries like <em>Django</em>, <em>NumPy</em>, <em>Scikit-learn</em>, and <em>Twisted</em>, and comes with the stackless mode, providing micro-threads for massive concurrency.</p>
<p>In this article, we’ll see how to install and use PyPy in our system.</p>
<h2 id="heading-installation">Installation</h2>
<p>PyPy comes with Python3 and Python2. Click <a target="_blank" href="https://pypy.org/download.html">here</a> to download the pre-built binary that is compatible with your system.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734191593153/42d7c040-0037-4021-915e-71a2947a01cb.png" alt="Download PyPy" class="image--center mx-auto" /></p>
<p>After downloading PyPy, you’ll get a compressed folder in your system. Now extract the content of the PyPy’s build folder into the desired path, and that’s it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734192165709/104af072-04bf-4621-b6e3-dc8890f8a443.png" alt="Extracted PyPy build" class="image--center mx-auto" /></p>
<p>But how to use it because we didn’t add PyPy’s path to system variables like we used to do in the case of CPython installation?</p>
<h2 id="heading-how-to-use-pypy">How to Use PyPy?</h2>
<p>It is recommended to use PyPy using a virtual environment. Let’s see how we can use PyPy from a virtual environment.</p>
<p>We’ll use <a target="_blank" href="https://pypi.org/project/virtualenv/">virtualenv</a> package to create a virtual environment. It is compatible with both CPython and PyPy. You’ll need to install this package (<code>pip install virtualenv</code>) to get started.</p>
<p>Open the command prompt or terminal and run the following command:</p>
<pre><code class="lang-python">PS &gt; virtualenv -p D:/SACHIN/pypy310/pypy.exe pypyenv
</code></pre>
<p>Let’s understand what the above command does:</p>
<ul>
<li><p><code>virtualenv</code>: A command to create a virtual environment using <code>virtualenv</code>.</p>
</li>
<li><p><code>-p</code>: Specifies the path to the Python interpreter that will be used in the virtual environment. It can also be written <code>--python</code>.</p>
</li>
<li><p><code>D:/SACHIN/pypy310/pypy.exe</code>: Path to PyPy interpreter.</p>
</li>
<li><p><code>pypyenv</code>: Species the name of the virtual environment.</p>
</li>
</ul>
<p>Run the command and PyPy will be ready to use.</p>
<p>You can check if you are using PyPy by running the following command:</p>
<pre><code class="lang-python">PS &gt; cd pypyenv
PS &gt; Scripts/activate
(pypyenv) PS &gt; cd ..
(pypyenv) PS &gt; python --version
Python <span class="hljs-number">3.10</span><span class="hljs-number">.14</span> (<span class="hljs-number">39</span>dc8d3c85a7, Aug <span class="hljs-number">27</span> <span class="hljs-number">2024</span>, <span class="hljs-number">14</span>:<span class="hljs-number">33</span>:<span class="hljs-number">33</span>)
[PyPy <span class="hljs-number">7.3</span><span class="hljs-number">.17</span> <span class="hljs-keyword">with</span> MSC v<span class="hljs-number">.1929</span> <span class="hljs-number">64</span> bit (AMD64)]
</code></pre>
<p>You’ll notice that we used <code>python</code> command to check the version of PyPy installed on the system because in the virtual environment, the <code>python</code> command becomes a symlink (or equivalent) to the interpreter used when creating the virtual environment.</p>
<h2 id="heading-installing-modules-using-pypy">Installing Modules Using PyPy</h2>
<p>The following command is used to install third-party modules using PyPy:</p>
<pre><code class="lang-python">PS &gt; pypy -m pip install module_name
</code></pre>
<p>You can directly install modules without writing <code>pypy -m</code>, if you are using PyPy as the main interpreter. If you are using PyPy within an isolated environment then activate the environment and use the above command to avoid any error.</p>
<p>Some third-party libraries such as <strong>Scipy</strong> create problems during the installation, so in that case, you can use <a target="_blank" href="https://doc.pypy.org/en/latest/install.html#using-conda">conda</a> with pypy3.9.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[10 Useful yet Rarely Used OS Functions in Python]]></title><description><![CDATA[You must have used functions provided by the os module in Python several times in your projects. These could be used to create a file, walk down a directory, get info on the current directory, perform path operations, and more.
In this article, we’ll...]]></description><link>https://teamgeek.geekpython.in/10-useful-yet-rarely-used-os-functions-in-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/10-useful-yet-rarely-used-os-functions-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[os]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 14 Nov 2024 13:50:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731172868340/39399f51-e487-455c-95b4-13c611a8c128.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You must have used functions provided by the <code>os</code> module in Python several times in your projects. These could be used to create a file, walk down a directory, get info on the current directory, perform path operations, and more.</p>
<p>In this article, we’ll discuss the functions that are as useful as any function in the <code>os</code> module but are rarely used.</p>
<h2 id="heading-ospathcommonpath">os.path.commonpath()</h2>
<p>When working with multiple files that share a common directory structure, you might want to find the longest shared path. <code>os.path.commonpath()</code> does just that. This can be helpful when organizing files or dealing with different paths across environments.</p>
<p>Here’s an example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

paths = [<span class="hljs-string">'/user/data/project1/file1.txt'</span>, <span class="hljs-string">'/user/data/project2/file2.txt'</span>]
common_path = os.path.commonpath(paths)
print(<span class="hljs-string">"Common Path:"</span>, common_path)
</code></pre>
<p>This code will give us the common path shared by these two paths.</p>
<pre><code class="lang-bash">Common Path: /user/data
</code></pre>
<p>You can see that <code>os.path.commonpath()</code> takes a list of path names, which might be impractical to manually write them down.</p>
<p>In that case, it is best to iterate over all of the directories, subdirectories, and file names and then look for the common path.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_file_paths</span>(<span class="hljs-params">directory, file_extension=None</span>):</span>
    <span class="hljs-comment"># Collect all file paths in the directory (and subdirectories, if any)</span>
    file_paths = []
    <span class="hljs-keyword">for</span> root, dirs, files <span class="hljs-keyword">in</span> os.walk(directory):
        <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files:
            <span class="hljs-keyword">if</span> file_extension <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">or</span> file.endswith(file_extension):
                file_paths.append(os.path.join(root, file))
    <span class="hljs-keyword">return</span> file_paths


<span class="hljs-comment"># Specify the root directory to start from</span>
directory_path = <span class="hljs-string">'D:/SACHIN/Pycharm/Flask-Tutorial'</span>

<span class="hljs-comment"># If you want to filter by file extension</span>
file_paths = get_file_paths(directory_path, file_extension=<span class="hljs-string">'.html'</span>)

<span class="hljs-comment"># Find the common path among all files</span>
<span class="hljs-keyword">if</span> file_paths:
    common_path = os.path.commonpath(file_paths)
    print(<span class="hljs-string">"Common Path:"</span>, common_path)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"No files found in the specified directory."</span>)
</code></pre>
<p>In this example, the function <code>get_file_paths()</code> traverses a directory from top to bottom and appends all the paths found in the <code>file_paths</code> list. This function optionally takes a file extension if we want to look out for specific files.</p>
<p>Now we can easily find the common path of any directory.</p>
<pre><code class="lang-python">Common Path: D:\SACHIN\Pycharm\Flask-Tutorial\templates
</code></pre>
<h2 id="heading-osscandir">os.scandir()</h2>
<p>If you’re using <code>os.listdir()</code> to get the contents of a directory, consider using <code>os.scandir()</code> instead. It’s not only faster but also returns <a target="_blank" href="https://docs.python.org/3/library/os.html#os.DirEntry"><code>DirEntry</code></a> objects, which provide useful information like file types, permissions, and whether the entry is a file or a directory.</p>
<p>Here’s an example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-keyword">with</span> os.scandir(<span class="hljs-string">'D:/SACHIN/Pycharm/osfunctions'</span>) <span class="hljs-keyword">as</span> entries:
    <span class="hljs-keyword">for</span> entry <span class="hljs-keyword">in</span> entries:
        print(<span class="hljs-string">f"<span class="hljs-subst">{entry.name}</span> : \n"</span>
              <span class="hljs-string">f"&gt;&gt;&gt;&gt; Is File: <span class="hljs-subst">{entry.is_file()}</span> \n"</span>
              <span class="hljs-string">f"&gt;&gt;&gt;&gt; Is Directory: <span class="hljs-subst">{entry.is_dir()}</span>"</span>)
</code></pre>
<p>In this example, we used <code>os.scandir()</code> and passed a directory and then we iterated over this directory and printed the info.</p>
<pre><code class="lang-bash">.idea : 
&gt;&gt;&gt;&gt; Is File: False 
&gt;&gt;&gt;&gt; Is Directory: True
main.py : 
&gt;&gt;&gt;&gt; Is File: True 
&gt;&gt;&gt;&gt; Is Directory: False
sample.py : 
&gt;&gt;&gt;&gt; Is File: True 
&gt;&gt;&gt;&gt; Is Directory: False
</code></pre>
<h2 id="heading-ospathsplitext">os.path.splitext()</h2>
<p>Let’s say you’re working with files and need to check their extension, you can get help from <code>os.path.splitext()</code> function. It splits the file path into the root and extension, which can help you determine the file type.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

filename = <span class="hljs-string">'report.csv'</span>
root, ext = os.path.splitext(filename)
print(<span class="hljs-string">f"Root: <span class="hljs-subst">{root}</span> \n"</span>
      <span class="hljs-string">f"Extension: <span class="hljs-subst">{ext}</span>"</span>)
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-python">Root: report 
Extension: .csv
</code></pre>
<p>Look at some cases where paths can be weird, at that time how <code>os.path.splitext()</code> works.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

filename = [<span class="hljs-string">'.report'</span>, <span class="hljs-string">'report'</span>, <span class="hljs-string">'report.case.txt'</span>, <span class="hljs-string">'report.csv.zip'</span>]
<span class="hljs-keyword">for</span> idx, paths <span class="hljs-keyword">in</span> enumerate(filename):
    root, ext = os.path.splitext(paths)
    print(<span class="hljs-string">f"<span class="hljs-subst">{idx}</span> - <span class="hljs-subst">{paths}</span>\n"</span>
          <span class="hljs-string">f"Root: <span class="hljs-subst">{root}</span> | Extension: <span class="hljs-subst">{ext}</span>"</span>)
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">0 - .report
Root: .report | Extension: 
1 - report
Root: report | Extension: 
2 - report.case.txt
Root: report.case | Extension: .txt
3 - report.csv.zip
Root: report.csv | Extension: .zip
</code></pre>
<h2 id="heading-osmakedirs">os.makedirs()</h2>
<p>There's already a frequently used function that allows us to create directories. But what about when you create nested directories?</p>
<p>Creating nested directories can be a hassle with <code>os.mkdir()</code> since it only makes one directory at a time. <code>os.makedirs()</code> allows you to create multiple nested directories in one go, and the <code>exist_ok=True</code> argument makes sure it doesn’t throw an error if the directory already exists.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

os.makedirs(<span class="hljs-string">'project/data/files'</span>, exist_ok=<span class="hljs-literal">True</span>)
print(<span class="hljs-string">"Nested directories created!"</span>)
</code></pre>
<p>When we run this program, it will create specified directories and sub-directories.</p>
<pre><code class="lang-bash">Nested directories created!
</code></pre>
<p>If we run the above program again, it won’t throw an error due to <code>exist_ok=True</code>.</p>
<h2 id="heading-osreplace">os.replace()</h2>
<p>Similar to <code>os.rename()</code>, <code>os.replace()</code> moves a file to a new location, but it safely overwrites any existing file at the destination. This is helpful for tasks where you’re updating or backing up files and want to ensure that old files are safely replaced.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

os.replace(src=<span class="hljs-string">'main.py'</span>, dst=<span class="hljs-string">'new_main.py'</span>)
print(<span class="hljs-string">"File replaced successfully!"</span>)
</code></pre>
<p>In this code, <code>main.py</code> file will be renamed to <code>new_main.py</code> just as <code>os.rename()</code> function but this operation is like take it all or nothing. It means the file replacement happens in a single, indivisible step, so either the entire operation succeeds or nothing changes at all.</p>
<pre><code class="lang-bash">File replaced successfully!
</code></pre>
<h2 id="heading-osurandom">os.urandom()</h2>
<p>For cryptographic purposes, you need a secure source of random data. <code>os.urandom()</code> generates random bytes suitable for things like generating random IDs, tokens, or passwords. It’s more secure than the <code>random</code> module for sensitive data.</p>
<p><code>os.urandom()</code> uses randomness generated by the operating system you are using from various resources to make bytes (data) unpredictable.</p>
<p>In Windows, it uses <code>BCryptGenRandom()</code> to generate random bytes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

secure_token = os.urandom(<span class="hljs-number">16</span>)  <span class="hljs-comment"># 16 bytes of random data</span>
print(<span class="hljs-string">"Secure Token:"</span>, secure_token)
<span class="hljs-comment">#Making it human-readable</span>
print(<span class="hljs-string">"Secure Token:"</span>, secure_token.hex())
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">Secure Token: b<span class="hljs-string">'\x84\xd6\x1c\x1bKB\x7f\xcd\xf6\xb7\xc4D\x92z\xe3{'</span>
Secure Token: 84d61c1b4b427fcdf6b7c444927ae37b
</code></pre>
<h2 id="heading-ospathsamefile">os.path.samefile()</h2>
<p>The <code>os.path.samefile()</code> function in Python is used to check if two paths refer to the <strong>same file</strong> or <strong>directory</strong> on the filesystem. It’s particularly helpful in scenarios where multiple paths might point to the same physical file, such as when dealing with symbolic links, hard links, or different absolute and relative paths to the same location.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

is_same = os.path.samefile(<span class="hljs-string">'/path/to/file1.txt'</span>, <span class="hljs-string">'/different/path/to/symlink_file1.txt'</span>)
print(<span class="hljs-string">"Are they the same file?"</span>, is_same)
</code></pre>
<p><code>os.path.samefile()</code> is designed to return <code>True</code> only if both paths reference the <strong>same file</strong> on disk, such as a file that’s hard-linked or symlinked to the same data on the filesystem.</p>
<h2 id="heading-ospathrelpath">os.path.relpath()</h2>
<p><code>os.path.relpath()</code> is a computation function that computes the relative path between two paths. This is particularly useful when building file paths dynamically or working with relative imports.</p>
<p>Consider the following example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-comment"># Target file path</span>
target_path = <span class="hljs-string">"D:/SACHIN/Pycharm/osfunctions/project/engine/log.py"</span>
<span class="hljs-comment"># Starting point</span>
start_path = <span class="hljs-string">"D:/SACHIN/Pycharm/osfunctions/project/interface/character/specific.py"</span>

relative_path = os.path.relpath(target_path, start=start_path)
print(relative_path)
</code></pre>
<p>In this example, we have <code>target_path</code> which contains a path where we have to navigate and <code>start_path</code> contains a path from where we have to start calculating the relative path to <code>target_path</code>.</p>
<p>When we run this, we get the following output.</p>
<pre><code class="lang-python">..\..\..\engine\log.py
</code></pre>
<p>This means we have to go up three directories and then down to <code>engine/log.py</code>.</p>
<h2 id="heading-osfsync">os.fsync()</h2>
<p>When we perform a file writing (<code>file.write()</code>) operation, the data isn’t saved to disk instantly instead the data is saved into the system’s buffer and if something unexpected happens before writing the data to the disk, the data gets lost.</p>
<p><code>os.fsync()</code> forces the data to be written, ensuring data integrity. It’s especially useful in logging or when writing critical data that must not be lost.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-keyword">with</span> open(<span class="hljs-string">'data.txt'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"gibberish!"</span>)
    os.fsync(f.fileno())  <span class="hljs-comment"># Ensures data is written to disk</span>
</code></pre>
<p><code>os.fsync(f.fileno())</code> is called to make sure the data is immediately written to the disk and not left in the buffer.</p>
<p><code>os.fsync()</code> takes file descriptor that’s why we passed <code>f.fileno()</code> which is a unique integer assigned by the system to the file on which we are operating.</p>
<h2 id="heading-osgetterminalsize">os.get_terminal_size()</h2>
<p>If you’re creating CLI tools, formatting the output to fit the terminal width can make the output cleaner. <code>os.get_terminal_size()</code> gives you the current terminal width and height, making it easy to dynamically format content.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

size = os.get_terminal_size()
print(<span class="hljs-string">f"Terminal Width: <span class="hljs-subst">{size.columns}</span>, Terminal Height: <span class="hljs-subst">{size.lines}</span>"</span>)
</code></pre>
<p>When we run this code in the terminal, we get the size of the terminal on which we are running this script.</p>
<pre><code class="lang-bash">PS &gt; py sample.py
Terminal Width: 158, Terminal Height: 12
</code></pre>
<p>Note: You may get an error when directly running the script on IDE where the program doesn’t have access to the terminal.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/stream-video-to-frontend-in-fastapi">Streaming videos on the frontend in FastAPI</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/circular-import-error-in-python">How to fix circular imports in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/template-inheritance-in-flask">Template inheritance in Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/type-hinting-in-python">How to use type hints in Python</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas">How to find and delete mismatched columns from datasets in pandas</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[How to Stream Video to Frontend in FastAPI]]></title><description><![CDATA[FastAPI is a fast and modern web framework known for its support for asynchronous REST API and ease of use.
In this article, we’ll see how to stream videos on frontend in FastAPI.
StreamingResponse
Stream Local Video
FastAPI provides a StreamingRespo...]]></description><link>https://teamgeek.geekpython.in/how-to-stream-video-to-frontend-in-fastapi</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-stream-video-to-frontend-in-fastapi</guid><category><![CDATA[FastAPI]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Wed, 06 Nov 2024 03:30:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730715086816/530d41c7-2b16-48d1-8dab-19c53e8b9ce0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>FastAPI is a fast and modern web framework known for its support for asynchronous REST API and ease of use.</p>
<p>In this article, we’ll see how to stream videos on frontend in FastAPI.</p>
<h2 id="heading-streamingresponse">StreamingResponse</h2>
<h3 id="heading-stream-local-video">Stream Local Video</h3>
<p>FastAPI provides a <code>StreamingResponse</code> class that is dedicated to streaming purposes. The <code>StreamingResponse</code> class takes a generator or iterator and streams the response.</p>
<p>Here’s a simple example of streaming local video to the browser.</p>
<pre><code class="lang-python"><span class="hljs-comment"># localvid.py</span>
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> fastapi.responses <span class="hljs-keyword">import</span> StreamingResponse

app = FastAPI()

<span class="hljs-comment"># Video path</span>
vid_path = <span class="hljs-string">'sample_video.mp4'</span>

<span class="hljs-comment"># Function to stream local video</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stream_local_video</span>():</span>
    <span class="hljs-keyword">with</span> open(vid_path, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> vid_file:
        <span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> vid_file

<span class="hljs-comment"># Path to stream video</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>():</span>
    <span class="hljs-keyword">return</span> StreamingResponse(stream_local_video(), media_type=<span class="hljs-string">'video/mp4'</span>)
</code></pre>
<p>We imported the <code>StreamingResponse</code> class from the <code>fastapi.responses</code> module.</p>
<p>In the <code>video_stream()</code> path operation function, we returned the response using <code>StreamingResponse</code>. We passed the generator function <code>stream_local_video()</code> and <code>media_type</code> as an argument to the <code>StreamingResponse</code> class.</p>
<p>The generator function <code>stream_local_video()</code> reads the bytes of the video and <code>yield from</code> iterates over the bytes and each part iterated is then yielded.</p>
<p>The following command will run the server and stream the video on <code>http://127.0.0.1:8000/</code>.</p>
<pre><code class="lang-python">&gt; fastapi dev localvid.py

 ╭────────── FastAPI CLI - Development mode ───────────╮
 │                                                     │
 │  Serving at: http://<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">8000</span>                  │
 │                                                     │
 │  API docs: http://<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>:<span class="hljs-number">8000</span>/docs               │
 │                                                     │
 │  Running <span class="hljs-keyword">in</span> development mode, <span class="hljs-keyword">for</span> production use:   │
 │                                                     │
 │  fastapi run                                        │
 │                                                     │
 ╰─────────────────────────────────────────────────────╯
</code></pre>
<h3 id="heading-stream-online-video">Stream Online Video</h3>
<pre><code class="lang-python"><span class="hljs-comment"># onlinevid.py</span>
<span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> fastapi.responses <span class="hljs-keyword">import</span> StreamingResponse
<span class="hljs-keyword">import</span> requests

app = FastAPI()

<span class="hljs-comment"># Video URL</span>
vid_url = <span class="hljs-string">'https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4'</span>

<span class="hljs-comment"># Function to stream online video</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stream_online_video</span>(<span class="hljs-params">url</span>):</span>
    response = requests.get(url, stream=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">for</span> portion <span class="hljs-keyword">in</span> response.iter_content(chunk_size=<span class="hljs-number">1024</span>*<span class="hljs-number">1024</span>):
        <span class="hljs-keyword">yield</span> portion

<span class="hljs-comment"># Path to stream video</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>():</span>
    <span class="hljs-keyword">return</span> StreamingResponse(stream_online_video(vid_url), media_type=<span class="hljs-string">'video/mp4'</span>)
</code></pre>
<p>In this example, we used the <code>requests</code> library to fetch the content of the video from the URL and we set the <code>stream=True</code> (avoids reading the video at once into memory). Then we iterated and yielded the video content in chunks (1024 bytes at a time).</p>
<p>When we run the server, it will serve the video from the URL.</p>
<p>Instead of a hardcoded URL, we can specify the URL in the endpoint.</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> fastapi.responses <span class="hljs-keyword">import</span> StreamingResponse
<span class="hljs-keyword">import</span> requests

app = FastAPI()

<span class="hljs-comment"># Function to stream online video</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stream_online_video</span>(<span class="hljs-params">url</span>):</span>
    response = requests.get(url, stream=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">for</span> portion <span class="hljs-keyword">in</span> response.iter_content(chunk_size=<span class="hljs-number">1024</span>*<span class="hljs-number">1024</span>):
        <span class="hljs-keyword">yield</span> portion

<span class="hljs-comment"># Path to stream video</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>(<span class="hljs-params">url</span>):</span>
    <span class="hljs-keyword">return</span> StreamingResponse(stream_online_video(url), media_type=<span class="hljs-string">'video/mp4'</span>)
</code></pre>
<p>In this example, we modified the path operation function <code>video_stream()</code> to accept a URL.</p>
<p>Now we can specify the URL of the video in the endpoint in the following format.</p>
<p><code>http://127.0.0.1:8000/?url=https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4</code></p>
<blockquote>
<p>We can also make the path operation function asynchronous using <code>async</code>.</p>
</blockquote>
<h2 id="heading-fileresponse">FileResponse</h2>
<h3 id="heading-stream-local-video-1">Stream Local Video</h3>
<p>The <code>FileResponse</code> class simply takes a file and streams the response.</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> fastapi.responses <span class="hljs-keyword">import</span> FileResponse

app = FastAPI()

<span class="hljs-comment"># Video path</span>
vid_path = <span class="hljs-string">'video.mp4'</span>

<span class="hljs-comment"># Path to stream video</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>():</span>
    <span class="hljs-keyword">return</span> FileResponse(vid_path, media_type=<span class="hljs-string">'video/mp4'</span>)
</code></pre>
<p>In the above example, we simply passed a video file in the <code>FileResponse</code> class and returned the response.</p>
<p>We didn’t read and iterate over the bytes of the video to stream it like we did in the case of <code>StreamingResponse</code>.</p>
<p>The <code>FileResponse</code> class is ideal for relatively small or medium-sized files as it loads the file in the memory. Large files will consume more memory.</p>
<h3 id="heading-stream-online-video-1">Stream Online Video</h3>
<p>Streaming video from the URL using <code>FileResponse</code> isn’t the same as streaming the local video. As we know, the <code>FileResponse</code> class takes a file and streams it.</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> fastapi.responses <span class="hljs-keyword">import</span> FileResponse
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os

app = FastAPI()

<span class="hljs-comment"># Video URL</span>
vid_url = <span class="hljs-string">'https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4'</span>
local_vid = <span class="hljs-string">'sample_video.mp4'</span>

<span class="hljs-comment"># Function to save video from URL</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">save_as_file</span>(<span class="hljs-params">url, path</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(path):
        response = requests.get(url)
        <span class="hljs-keyword">with</span> open(<span class="hljs-string">'sample_video.mp4'</span>, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> vid:
            vid.write(response.content)

save_as_file(vid_url, local_vid)

<span class="hljs-comment"># Path to stream video</span>
<span class="hljs-meta">@app.get("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>():</span>
    <span class="hljs-keyword">return</span> FileResponse(local_vid, media_type=<span class="hljs-string">'video/mp4'</span>)
</code></pre>
<p>In this example, instead of streaming the local video, we streamed the video from the URL using <code>FileResponse</code>.</p>
<p>This isn’t the best practice because we first saved the video from the URL in the local machine and then streamed the video.</p>
<p>The <code>FileResponse</code> class can be best utilized for local files, not web content.</p>
<p>That was all about streaming video directly to the browser but we don’t want to do that every time, instead, we want the video to be streamed on our website’s landing page.</p>
<h2 id="heading-stream-video-on-frontend">Stream Video on Frontend</h2>
<p>So, <strong>how to stream video on the frontend using FastAPI?</strong> We need to create a frontend using HTML and then stream the video.</p>
<p>First, create a directory named <code>serve_video</code> or whatever you want to name it, and create the following files and sub-directories.</p>
<pre><code class="lang-bash">serve_video/
   - templates/
      - display_video.html
   - app.py
</code></pre>
<p>The <code>app.py</code> file will contain our backend code and the <code>display_video.html</code> file will contain frontend code.</p>
<p><code>app.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Request
<span class="hljs-keyword">from</span> fastapi.responses <span class="hljs-keyword">import</span> StreamingResponse, HTMLResponse
<span class="hljs-keyword">from</span> fastapi.templating <span class="hljs-keyword">import</span> Jinja2Templates
<span class="hljs-keyword">import</span> requests

app = FastAPI()
templates = Jinja2Templates(directory=<span class="hljs-string">"templates"</span>)

vid_urls = [
    <span class="hljs-string">"https://cdn.pixabay.com/video/2023/07/28/173530-849610807_large.mp4"</span>,
    <span class="hljs-string">'https://cdn.pixabay.com/video/2024/03/31/206294_large.mp4'</span>,
    <span class="hljs-string">'https://cdn.pixabay.com/video/2023/10/11/184510-873463500_large.mp4'</span>,
    <span class="hljs-string">'https://cdn.pixabay.com/video/2023/06/17/167569-837244635_large.mp4'</span>
]

<span class="hljs-comment"># Stream the video from the URL</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stream_video</span>(<span class="hljs-params">url</span>):</span>
    response = requests.get(url, stream=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">for</span> portion <span class="hljs-keyword">in</span> response.iter_content(chunk_size=<span class="hljs-number">1024</span>*<span class="hljs-number">1024</span>):
        <span class="hljs-keyword">yield</span> portion

<span class="hljs-comment"># Endpoint to render the HTML template with the video player</span>
<span class="hljs-meta">@app.get("/", response_class=HTMLResponse)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_template</span>(<span class="hljs-params">request: Request</span>):</span>
    <span class="hljs-keyword">return</span> templates.TemplateResponse(<span class="hljs-string">"display_video.html"</span>, {<span class="hljs-string">"request"</span>: request})

<span class="hljs-comment"># Endpoint to stream the video</span>
<span class="hljs-meta">@app.get("/video/{video_id}")</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">video_stream</span>(<span class="hljs-params">vid_id: int</span>):</span>
    <span class="hljs-keyword">if</span> <span class="hljs-number">0</span> &lt;= vid_id &lt; len(vid_urls):
        <span class="hljs-keyword">return</span> StreamingResponse(stream_video(vid_urls[vid_id]), media_type=<span class="hljs-string">"video/mp4"</span>)
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> HTMLResponse(<span class="hljs-string">"Video not found"</span>, status_code=<span class="hljs-number">404</span>)
</code></pre>
<p>In this example, we are streaming multiple videos on the frontend. We have a list of video URLs stored within <code>vid_urls</code>.</p>
<p>We have a <code>stream_video()</code> generator function that yields the video in smaller chunks.</p>
<p>We created an asynchronous path operation function <code>video_template()</code> that returns a response from HTML (<code>@app.get("/", response_class=HTMLResponse)</code>) file.</p>
<p>We are serving HTML from a template stored within the <code>templates</code> directory, so, we set up a Jinja2 template directory where HTML templates are stored (<code>templates = Jinja2Templates(directory="templates")</code>). This is where FastAPI will look for <code>.html</code> files.</p>
<blockquote>
<p>Note: To render templates in FastAPI, you need to install the Jinja2 (<code>pip install jinja2</code>) library.</p>
</blockquote>
<p>Then we returned the response using <code>templates.TemplateResponse("display_video.html", {"request": request})</code>. We passed our HTML template <code>display_video.html</code> and along with it, a dictionary containing <code>Request</code> object (<code>{"request": request}</code>). This <code>Request</code> object provides information about the incoming HTTP request, such as headers, cookies, and URLs, which can be accessed within the HTML template.</p>
<p>Next, we created an endpoint (<code>@app.get("/video/{video_id}")</code>) to stream individual videos based on the ID in the <code>vid_ulrs</code>. The <code>video_stream(vid_id: int)</code> path operation functions accept the index of the video in <code>vid_urls</code>.</p>
<p>Within the <code>video_stream()</code>, the <code>if</code> condition checks if the <code>vid_id</code> is within the range, if not, then raises an error otherwise the video is streamed based on the specified index.</p>
<p><code>display_video.html</code></p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Stooooockzz<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>What we do?<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>We create awesome stock videos for free usage<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Video Samples<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"display: flex; justify-content: space-evenly;"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">width</span>=<span class="hljs-string">'20%'</span> <span class="hljs-attr">height</span>=<span class="hljs-string">'30%'</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border-radius: 10px;"</span> <span class="hljs-attr">controls</span> <span class="hljs-attr">autoplay</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/video/0"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">width</span>=<span class="hljs-string">'20%'</span> <span class="hljs-attr">height</span>=<span class="hljs-string">'30%'</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border-radius: 10px;"</span> <span class="hljs-attr">controls</span> <span class="hljs-attr">autoplay</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/video/1"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">width</span>=<span class="hljs-string">'20%'</span> <span class="hljs-attr">height</span>=<span class="hljs-string">'30%'</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border-radius: 10px;"</span> <span class="hljs-attr">controls</span> <span class="hljs-attr">autoplay</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/video/2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">width</span>=<span class="hljs-string">'20%'</span> <span class="hljs-attr">height</span>=<span class="hljs-string">'30%'</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border-radius: 10px;"</span> <span class="hljs-attr">controls</span> <span class="hljs-attr">autoplay</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/video/3"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This HTML file contains multiple <code>&lt;video&gt;</code> tags with the source pointing to the <code>/video/{video_id}</code> endpoint that streams the video based on ID.</p>
<p>Here, we passed <code>&lt;source src="/video/0" type="video/mp4"&gt;</code> within the <code>&lt;video&gt;</code> tag that represents streaming the first video from the <code>vid_urls</code> (in <code>app.py</code>) list. Similarly, we specified the same source but changed the ID within each <code>&lt;video&gt;</code> tag.</p>
<pre><code class="lang-bash">&gt; fastapi dev app.py
</code></pre>
<p>Upon running the server using the above command, we get the following response on the frontend.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730712807026/90000ce3-b592-438f-929b-e8dbe071684b.png" alt="Streaming multiple videos on frontend" class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We’ve used <code>StreaminResponse</code> and <code>FileResponse</code> classes to stream local and web videos directly on the browser, and along with this we’ve also streamed multiple videos using <code>StreamingResponse</code> which was rendered using HTML files on the browser.</p>
<p>In this article, we’ve used URLs of the video residing on the internet but you can also fetch URLs from databases, local files, disks, etc.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[How to Fix Circular Imports in Python]]></title><description><![CDATA[Have you ever come across circular imports in Python? Well, it’s a very common code smell that indicates something’s wrong with the design or structure.
Circular Import Example
How does circular import occur? This import error usually occurs when two...]]></description><link>https://teamgeek.geekpython.in/how-to-fix-circular-imports-in-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-fix-circular-imports-in-python</guid><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Sat, 02 Nov 2024 18:30:38 GMT</pubDate><content:encoded><![CDATA[<p>Have you ever come across <strong>circular imports</strong> in Python? Well, it’s a very common <a target="_blank" href="https://en.wikipedia.org/wiki/Code_smell">code smell</a> that indicates something’s wrong with the design or structure.</p>
<h2 id="heading-circular-import-example">Circular Import Example</h2>
<p><strong>How does circular import occur?</strong> This import error usually occurs when two or more modules depending on each other try to import before fully initializing.</p>
<p>Let’s say we have two modules: <code>module_1.py</code> and <code>module_2.py</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-keyword">from</span> module_2 <span class="hljs-keyword">import</span> ModY
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
    mody_obj = ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-keyword">from</span> module_1 <span class="hljs-keyword">import</span> ModX
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
    modx_obj = ModX()
</code></pre>
<p>In the above code snippets, both <code>module_1</code> and <code>module_2</code> are mutually dependent on each other.</p>
<p>The initialization of <code>mody_obj</code> in <code>module_1</code> depends on <code>module_2</code> and the initialization of <code>modx_obj</code> in <code>module_2</code> depends on <code>module_1</code>.</p>
<p>This is what we call a circular dependency. Both modules will stuck in the import loops while attempting to load each other.</p>
<p>If we run module_1.py, we’ll get the following traceback.</p>
<pre><code class="lang-bash">Traceback (most recent call last):
  File <span class="hljs-string">"module_1.py"</span>, line 1, <span class="hljs-keyword">in</span> &lt;module&gt;
    from module_2 import ModY
  File <span class="hljs-string">"module_2.py"</span>, line 1, <span class="hljs-keyword">in</span> &lt;module&gt;
    from module_1 import ModX
  File <span class="hljs-string">"module_1.py"</span>, line 1, <span class="hljs-keyword">in</span> &lt;module&gt;
    from module_2 import ModY
ImportError: cannot import name <span class="hljs-string">'ModY'</span> from partially initialized module <span class="hljs-string">'module_2'</span> (most likely due to a circular import)
</code></pre>
<p>This error explains the situation of circular import. When the program attempted to import <code>ModY</code> from <code>module_2</code>, at that time <code>module_2</code> wasn’t fully initialized (due to another import statement that attempts to import <code>ModX</code> from <code>module_1</code>).</p>
<p><strong>How to fix circular imports in Python?</strong> There are different ways to get rid of circular imports in Python.</p>
<h2 id="heading-fix-circular-imports-in-python">Fix Circular Imports in Python</h2>
<h3 id="heading-move-code-into-a-common-file">Move code into a common file</h3>
<p>We can move the code into a common file to avoid import errors and then try to import the modules from that file.</p>
<pre><code class="lang-python"><span class="hljs-comment"># main.py ----&gt; common file</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
    <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p>In the above code snippet, we moved the classes <code>ModX</code> and <code>ModY</code> into a common file (<code>main.py</code>).</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-keyword">from</span> main <span class="hljs-keyword">import</span> ModY

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mod_X</span>:</span>
    mody_obj = ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-keyword">from</span> main <span class="hljs-keyword">import</span> ModX

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mod_Y</span>:</span>
    modx_obj = ModX()
</code></pre>
<p>Now, <code>module_1</code> and <code>module_2</code> import the classes from <code>main</code> which fixes the circular import situation.</p>
<p>There is a problem with this approach, sometimes the codebase is so large that it becomes risky to move the code into another file.</p>
<h3 id="heading-move-the-import-to-the-end-of-the-module">Move the import to the end of the module</h3>
<p>We can shift the import statement at the end of the module. This will give time to fully initialize the module before importing another module.</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
   <span class="hljs-keyword">pass</span>

<span class="hljs-keyword">from</span> module_2 <span class="hljs-keyword">import</span> ModY

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mod_X</span>:</span>
   mody_obj = ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
   <span class="hljs-keyword">pass</span>

<span class="hljs-keyword">from</span> module_1 <span class="hljs-keyword">import</span> ModX
</code></pre>
<h3 id="heading-importing-module-within-the-classfunction-scope">Importing module within the class/function scope</h3>
<p>Importing modules within the class or function scope can avoid circular imports. This allows the module to be imported only when the class or function is invoked. It’s relevant when we want to minimize memory use.</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
  <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mod_X</span>:</span>
   <span class="hljs-keyword">from</span> module_2 <span class="hljs-keyword">import</span> ModY
   mody_obj = ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
   <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mod_Y</span>:</span>
   <span class="hljs-keyword">from</span> module_1 <span class="hljs-keyword">import</span> ModX
   modx_obj = ModX()
</code></pre>
<p>We moved the import statements within classes <code>Mod_X</code> and <code>Mod_Y</code> scope in <code>module_1</code> and <code>module_2</code> respectively.</p>
<p>If we run either <code>module_1</code> or <code>module_2</code>, we’ll not get a circular import error. But, this approach makes the class accessible only within the class’s scope, so we can’t leverage the import globally.</p>
<h3 id="heading-using-module-namealias">Using module name/alias</h3>
<p>Using the module name or just an alias like this solves the problem. This allows both modules to load fully by deferring circular dependency until runtime.</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-keyword">import</span> module_2 <span class="hljs-keyword">as</span> m2

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.mody_obj = m2.ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-keyword">import</span> module_1 <span class="hljs-keyword">as</span> m1

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.modx_obj = m1.ModX()
</code></pre>
<h3 id="heading-using-importlib-library">Using importlib library</h3>
<p>We can also use the <code>importlib</code> library to import the modules dynamically.</p>
<pre><code class="lang-python"><span class="hljs-comment"># module_1.py</span>
<span class="hljs-keyword">import</span> importlib

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        m2 = importlib.import_module(<span class="hljs-string">'module_2'</span>)
        self.mody_obj = m2.ModY()
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># module_2.py</span>
<span class="hljs-keyword">import</span> importlib

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        m1 = importlib.import_module(<span class="hljs-string">'module_1'</span>)
        self.mody_obj = m1.ModX()
</code></pre>
<h2 id="heading-circular-imports-in-python-packages">Circular Imports in Python Packages</h2>
<p>Usually, <strong>circular imports</strong> <strong>come from modules within the same package</strong>. In complex projects, the directory structure is also complex, with packages within packages.</p>
<p>These packages and sub-packages contain <code>__init__.py</code> files to provide easier access to modules. That’s where sometimes arises circular dependencies among modules unintentionally.</p>
<p>We have the following directory structure.</p>
<pre><code class="lang-bash">root_dir/
|- mainpkg/
|---- modpkg_x/
|-------- __init__.py
|-------- module_1.py
|-------- module_1_1.py
|---- modpkg_y/
|-------- __init__.py
|-------- module_2.py
|---- __init__.py
|- main.py
</code></pre>
<p>We have a package <code>mainpkg</code> and a <code>main.py</code> file. We have two sub-packages <code>modpkg_x</code> and <code>modpkg_y</code> within <code>mainpkg</code>.</p>
<p>Here’s what each Python file within <code>modpkg_x</code> and <code>modpkg_y</code> looks like.</p>
<p><code>mainpkg</code>/<code>modpkg_x</code>/<code>__init__.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> .module_1 <span class="hljs-keyword">import</span> ModX
<span class="hljs-keyword">from</span> .module_1_1 <span class="hljs-keyword">import</span> ModA
</code></pre>
<p>This file imports both classes (<code>ModX</code> and <code>ModA</code>) from <code>module_1</code> and <code>module_1_1</code>.</p>
<p><code>mainpkg</code>/<code>modpkg_x</code>/<code>module_1.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> ..modpkg_y.module_2 <span class="hljs-keyword">import</span> ModY
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModX</span>:</span>
    mody_obj = ModY()
</code></pre>
<p>The <code>module_1</code> imports a class <code>ModY</code> from <code>module_2</code>.</p>
<p><code>mainpkg</code>/<code>modpkg_x</code>/<code>module_1_1.py</code></p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModA</span>:</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p>The <code>module_1_1</code> imports nothing. It is not dependent on any module.</p>
<p><code>mainpkg</code>/<code>modpkg_y</code>/<code>__init__.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> .module_2 <span class="hljs-keyword">import</span> ModY
</code></pre>
<p>This file imports the class <code>ModY</code> from <code>module_2</code>.</p>
<p><code>mainpkg</code>/<code>modpkg_y</code>/<code>module_2.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> ..modpkg_x.module_1_1 <span class="hljs-keyword">import</span> ModA
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModY</span>:</span>
    moda_obj = ModA()
</code></pre>
<p>The <code>module_2</code> imports a class <code>ModA</code> from the <code>module_1_1</code>.</p>
<p>We have the following code within the <code>main.py</code> file.</p>
<p><code>root_dir</code>/<code>main.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> mainpkg.modpkg_y.module_2 <span class="hljs-keyword">import</span> ModY

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mody</span>():</span>
    y_obj = ModY()

mody()
</code></pre>
<p>The <code>main</code> file imports a class <code>ModY</code> from <code>module_2</code>. This file is dependent on <code>module_2</code>.</p>
<p>If we visualize the import cycle here, it would look like the following ignoring the <code>__init__.py</code> files within the <code>modpkg_x</code> and <code>modpkg_y</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730475880376/aa41eeed-f48e-4f48-a9f0-05665792ab2a.png" alt="Import cycle" class="image--center mx-auto" /></p>
<p>We can see that the <code>main</code> file depends on <code>module_2</code>, <code>module_1</code> also depends on <code>module_2</code> and <code>module_2</code> depends on <code>module_1_1</code>. There is no import cycle.</p>
<p>But you know, modules depend on their <code>__init__.py</code> file, so the <code>__init__.py</code> file initializes first, and modules are re-imported.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730475932370/b9a186b3-a2a0-46fb-98b9-cdf5bdf7124c.png" alt="Import cycle changed due to __init__.py file" class="image--center mx-auto" /></p>
<p>This is what the import cycle looks like now.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730475975886/20c22cbc-4b9b-4d98-9657-b03d36db6fca.png" alt="Final import cycle" class="image--center mx-auto" /></p>
<p>This made <code>module_1_1</code> depend on <code>module_1</code>, which is a fake dependency.</p>
<p>If this is the case, empty the sub-packages <code>__init__.py</code> files and using a separate <code>__init__.py</code> file can help by centralizing imports at the package level.</p>
<pre><code class="lang-bash">root_dir/
|- mainpkg/
|---- modpkg_x/
|-------- __init__.py  <span class="hljs-comment"># empty file</span>
|-------- module_1.py
|-------- module_1_1.py
|---- modpkg_y/
|-------- __init__.py  <span class="hljs-comment"># empty file</span>
|-------- module_2.py
|---- subpkg/
|-------- __init__.py
|---- __init__.py
|- main.py
</code></pre>
<p>In this structure, we added another sub-package <code>subpkg</code> within <code>mainpkg</code>.</p>
<p><code>mainpkg</code>/<code>subpkg</code>/<code>__init__.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> ..modpkg_x.module_1 <span class="hljs-keyword">import</span> ModX
<span class="hljs-keyword">from</span> ..modpkg_x.module_1_1 <span class="hljs-keyword">import</span> ModA
<span class="hljs-keyword">from</span> ..modpkg_y.module_2 <span class="hljs-keyword">import</span> ModY
</code></pre>
<p>This will allow internal modules to import from a single source, reducing the need for cross-imports.</p>
<p>Now we can update the import statement within the <code>main.py</code> file.</p>
<p><code>root_dir</code>/<code>main.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> mainpkg.subpkg <span class="hljs-keyword">import</span> ModY
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mody</span>():</span>
    y_obj = ModY()

mody()
</code></pre>
<p>This solves the problem of circular dependency between the modules within the same package.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Circular dependency or import in Python is a <a target="_blank" href="https://en.wikipedia.org/wiki/Code_smell"><strong>code smell</strong></a> which is an indication of serious re-structuring and refactoring of the code.</p>
<p>You can try any of these above-mentioned ways to avoid circular dependency in Python.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[How To Connect Database With Python]]></title><description><![CDATA[In this article, we’ll learn how to connect MySQL database with Python using the PyMySQL database driver.
Connect Database with Python
First, we need to install a MySQL database driver called PyMySQL that will help us bridge Python and MySQL.
pip ins...]]></description><link>https://teamgeek.geekpython.in/how-to-connect-database-with-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-connect-database-with-python</guid><category><![CDATA[MySQL]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Sat, 02 Nov 2024 08:17:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726309421891/d361d65b-6c23-4f27-8181-fe0c8caed9e3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we’ll learn how to connect <strong>MySQL database</strong> with <strong>Python</strong> using the <strong>PyMySQL</strong> database driver.</p>
<h1 id="heading-connect-database-with-python">Connect Database with Python</h1>
<p>First, we need to install a MySQL database driver called <strong>PyMySQL</strong> that will help us bridge Python and MySQL.</p>
<pre><code class="lang-python">pip install PyMySQL
</code></pre>
<p>Now, after installing this package, we can start the connection process by importing it into our Python script.</p>
<p>Create a Python file, let’s say <strong>db_connection.py</strong>, and write the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pymysql

<span class="hljs-comment"># Establish MySQL connection with Python</span>
sql_connection = pymysql.connect(
    host=<span class="hljs-string">"localhost"</span>,
    user=<span class="hljs-string">"root"</span>,
    password=<span class="hljs-string">"xxxxxxxxx"</span>,
    database=<span class="hljs-string">"consumer"</span>,
    cursorclass=pymysql.cursors.DictCursor
)

print(<span class="hljs-string">"Connected to database."</span>)

<span class="hljs-comment"># Create cursor to interact with database</span>
cursor = sql_connection.cursor()

<span class="hljs-comment"># Create an entry in the database</span>
cursor.execute(
      <span class="hljs-string">"""INSERT INTO consumers (name, address, phone)
      values ('Max', '21 St. Parkway', 871231);"""</span>
)

<span class="hljs-comment"># Save the changes in the database</span>
sql_connection.commit()

<span class="hljs-comment"># Fetch data from the database</span>
cursor.execute(
      <span class="hljs-string">"""SELECT * FROM consumers;"""</span>
)

data = cursor.fetchall()
print(data[<span class="hljs-number">0</span>])

<span class="hljs-comment"># Close the connection with database</span>
sql_connection.close()

print(<span class="hljs-string">"Operation successful."</span>)
</code></pre>
<p>This code creates a connection to the MySQL database and then writes an entry in the database table.</p>
<p>First, the package is imported which will help us bridge Python and MySQL using Python code.</p>
<p>Next, we established a connection using <code>pymysql.connect()</code> and passed the required arguments:</p>
<ul>
<li><p><code>hostname</code>: The location of the MySQL database. We have a MySQL server in the local system hence, we passed <code>"localhost"</code>.</p>
</li>
<li><p><code>user</code>: Username of the MySQL server. In this case, we passed <code>"root"</code>, which is a default name.</p>
</li>
<li><p><code>password</code>: Password of the MySQL server.</p>
</li>
<li><p><code>database</code>: The name of the database with which you want to connect. In this case, we are connecting to the <code>"consumer"</code> database on the server.</p>
</li>
<li><p><code>cursorclass</code>: This decides the format of the result returned by the cursor. In this case, the cursor will return results in a dictionary (<code>DictCursor</code>) format.</p>
</li>
</ul>
<p>Then we created a cursor (<code>sql_connection.cursor()</code>) object that helps in executing SQL queries.</p>
<p>Using <code>cursor.execute()</code>, we executed an SQL query to insert an entry in the <code>consumers</code> table of the <code>consumer</code> database.</p>
<p>Then we saved the changes to the database using <code>sql_connection.commit()</code>.</p>
<p>We then executed an SQL query to get all the data from the <code>consumers</code> table in the database.</p>
<p>Using <code>cursor.fetchall()</code>, we fetched all the entries from the table and printed the first result.</p>
<p>Finally, we closed the connection with the database using <code>sql_connection.close()</code>.</p>
<p>Now, when we run this code, we’ll get the following result.</p>
<pre><code class="lang-bash">Connected to database.
{<span class="hljs-string">'name'</span>: <span class="hljs-string">'Max'</span>, <span class="hljs-string">'address'</span>: <span class="hljs-string">'21 St. Parkway'</span>, <span class="hljs-string">'phone'</span>: 871231}
Operation successful.
</code></pre>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Insert Multiple Data Within Database Using Single SQL Query in Python]]></title><description><![CDATA[In this article, we’ll learn how to insert multiple entries or data in the database using a single SQL query in Python.
Insert Multiple Entries in the Database
We’ll see how we can insert multiple entries in the two different databases SQLite and MyS...]]></description><link>https://teamgeek.geekpython.in/insert-multiple-data-within-database-using-single-sql-query-in-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/insert-multiple-data-within-database-using-single-sql-query-in-python</guid><category><![CDATA[SQL]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Wed, 23 Oct 2024 16:54:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726383179015/6a78c667-ae21-4873-89e1-d385fcd8f6df.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we’ll learn how to insert multiple entries or data in the database using a single SQL query in Python.</p>
<h1 id="heading-insert-multiple-entries-in-the-database">Insert Multiple Entries in the Database</h1>
<p>We’ll see how we can insert multiple entries in the two different databases SQLite and MySQL.</p>
<h1 id="heading-sqlite">SQLite</h1>
<p>Create a Python file and write the following code inside it.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sqlite3

<span class="hljs-comment"># Create and connect with database</span>
connection = sqlite3.connect(<span class="hljs-string">"cars.db"</span>)

<span class="hljs-comment"># Create cursor to interact with database</span>
cursor = connection.cursor()

<span class="hljs-comment"># Create database table</span>
cursor.execute(
    <span class="hljs-string">"""CREATE TABLE IF NOT EXISTS car (brand text, model text)"""</span>
)

entries = [
    (<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'812 Superfast'</span>),
    (<span class="hljs-string">'Porsche'</span>, <span class="hljs-string">'Carrera GT'</span>),
    (<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'i8'</span>),
    (<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'X7'</span>),
    (<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'488 GTB'</span>)
]

<span class="hljs-comment"># Insert entries in the database table</span>
cursor.executemany(
    <span class="hljs-string">"""INSERT INTO car (brand, model) VALUES (?, ?)"""</span>, entries
)

<span class="hljs-comment"># Commit the changes</span>
connection.commit()

<span class="hljs-comment"># Fetch the result from the database table</span>
result = cursor.execute(
    <span class="hljs-string">"""SELECT * FROM car"""</span>
)

<span class="hljs-comment"># Print the entries in the table</span>
data = result.fetchall()
<span class="hljs-keyword">for</span> each <span class="hljs-keyword">in</span> data:
    print(each)

<span class="hljs-comment"># Close the database connection</span>
connection.close()
</code></pre>
<p>This code imports the <code>sqlite3</code> library that helps create and interact with the SQLite database.</p>
<p>We created and connected (<code>sqlite3.connect("cars.db")</code>) to the <code>cars.db</code> database and then created a cursor (<code>connection.cursor()</code>) to interact with the database.</p>
<p>Using the cursor, we executed an SQL query to create a table named <code>car</code> with two columns: <code>brand</code> and <code>model</code> in the database.</p>
<p>Then, we have a list of tuples containing the car information stored in the <code>entries</code> variable.</p>
<p>Now if you look closely, we used executemany() that will run for every parameter (entries). This single line is executed five times for five different entries.</p>
<blockquote>
<p>We used question mark (?) in the SQL query as a placeholder for the values. In SQLite, question mark (?) is used as a placeholder but for MySQL or PostgreSQL, this will be different.</p>
</blockquote>
<p>Next, the changes were saved using <code>connection.commit()</code>.</p>
<p>Another SQL query was executed to select all of the data from the table, which was then retrieved using <code>fetchall()</code> and printed.</p>
<p>Finally, the database connection was closed using <code>connection.close()</code>.</p>
<pre><code class="lang-bash">(<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'812 Superfast'</span>)
(<span class="hljs-string">'Porsche'</span>, <span class="hljs-string">'Carrera GT'</span>)
(<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'i8'</span>)
(<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'X7'</span>)
(<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'488 GTB'</span>)
</code></pre>
<h1 id="heading-mysql">MySQL</h1>
<p>Create a Python file and write the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pymysql

<span class="hljs-comment"># Establish MySQL connection with Python</span>
sql_connection = pymysql.connect(
    host=<span class="hljs-string">"localhost"</span>,
    user=<span class="hljs-string">"root"</span>,
    password=<span class="hljs-string">"xxxxxx"</span>,
    database=<span class="hljs-string">'cars'</span>,
    cursorclass=pymysql.cursors.DictCursor
)

<span class="hljs-comment"># Create cursor to interact with database</span>
cursor = sql_connection.cursor()

<span class="hljs-comment"># Create database table</span>
cursor.execute(
    <span class="hljs-string">"""CREATE TABLE IF NOT EXISTS car (brand text, model text)"""</span>
)

<span class="hljs-comment"># Entries to be made</span>
entries = [
    (<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'812 Superfast'</span>),
    (<span class="hljs-string">'Porsche'</span>, <span class="hljs-string">'Carrera GT'</span>),
    (<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'i8'</span>),
    (<span class="hljs-string">'BMW'</span>, <span class="hljs-string">'X7'</span>),
    (<span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'488 GTB'</span>)
]

<span class="hljs-comment"># Insert entries in the database table</span>
cursor.executemany(
    <span class="hljs-string">"""INSERT INTO car (brand, model) VALUES (%s, %s)"""</span>, entries
)

<span class="hljs-comment"># Save the changes in the database</span>
sql_connection.commit()

<span class="hljs-comment"># Fetch data from the database table</span>
cursor.execute(
      <span class="hljs-string">"""SELECT * FROM car"""</span>
)

data = cursor.fetchall()
<span class="hljs-keyword">for</span> each <span class="hljs-keyword">in</span> data:
    print(each)

<span class="hljs-comment"># Close the connection with database</span>
sql_connection.close()
</code></pre>
<p>In this code, we’ve used the <strong>PyMySQL</strong> database driver to connect with the MySQL database in Python.</p>
<p>We performed all the preliminary operations such as connecting to MySQL server and creating a cursor object using PyMySQL.</p>
<p>Then, we created a table named <code>car</code> with two columns within the <code>cars</code> database by executing an SQL query.</p>
<p>Next, we stored a list of tuples containing relevant data for the table in the <code>entries</code> variable.</p>
<p>Then we used <code>executemany()</code> to execute a single query repeatedly for each entry. This operation will insert every entry in the table stored in the entries variable.</p>
<blockquote>
<p>In MySQL, we use (%s) as a placeholder for a value.</p>
</blockquote>
<p>Next, the changes were saved using <code>connection.commit()</code>.</p>
<p>Then, we selected all rows in the database table <code>car</code> by executing an SQL query. The selected rows were then fetched using <code>fetchall()</code> and printed.</p>
<pre><code class="lang-bash">{<span class="hljs-string">'brand'</span>: <span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'model'</span>: <span class="hljs-string">'812 Superfast'</span>}
{<span class="hljs-string">'brand'</span>: <span class="hljs-string">'Porsche'</span>, <span class="hljs-string">'model'</span>: <span class="hljs-string">'Carrera GT'</span>}
{<span class="hljs-string">'brand'</span>: <span class="hljs-string">'BMW'</span>, <span class="hljs-string">'model'</span>: <span class="hljs-string">'i8'</span>}
{<span class="hljs-string">'brand'</span>: <span class="hljs-string">'BMW'</span>, <span class="hljs-string">'model'</span>: <span class="hljs-string">'X7'</span>}
{<span class="hljs-string">'brand'</span>: <span class="hljs-string">'Ferrari'</span>, <span class="hljs-string">'model'</span>: <span class="hljs-string">'488 GTB'</span>}
</code></pre>
<p>We got the results in a dictionary format because we set the cursor class to <code>DictCursor</code>.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Pandas df.ffill() and df.bfill()]]></title><description><![CDATA[The DataFrame.ffill() (forward fill) propagates missing or NaN values using the previous valid value in a column or row, while DataFrame.bfill() (backward fill) propagates them using the next valid value.
Let's see how and when to use them.
DataFrame...]]></description><link>https://teamgeek.geekpython.in/pandas-dfffill-and-dfbfill</link><guid isPermaLink="true">https://teamgeek.geekpython.in/pandas-dfffill-and-dfbfill</guid><category><![CDATA[pandas]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Wed, 23 Oct 2024 14:41:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723658290624/e2b62469-15c4-4e93-a73b-9a8148eed420.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <code>DataFrame.ffill()</code> (forward fill) propagates missing or <code>NaN</code> values using the <strong>previous</strong> valid value in a column or row, while <code>DataFrame.bfill()</code> (backward fill) propagates them using the <strong>next</strong> valid value.</p>
<p>Let's see how and when to use them.</p>
<h2 id="heading-dataframeffill">DataFrame.ffill()</h2>
<p>The <code>DataFrame.ffill()</code> method fills the missing or <code>NaN</code> values using the <strong>previous</strong> valid value in a column or row.</p>
<p>Suppose we have the following dataset that contains missing values in each column.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

df = pd.DataFrame(
    {
        <span class="hljs-string">"Max Temperature"</span>: [<span class="hljs-number">22.7</span>, <span class="hljs-number">24.8</span>, np.nan, np.nan, <span class="hljs-number">29.9</span>, np.nan, <span class="hljs-number">45</span>],
        <span class="hljs-string">"Min Temperature"</span>: [np.nan, <span class="hljs-number">20.1</span>, <span class="hljs-number">18.4</span>, np.nan, np.nan, np.nan, <span class="hljs-number">15.5</span>],
        <span class="hljs-string">"Avg Temperature"</span>: [<span class="hljs-number">21.4</span>, <span class="hljs-number">23.5</span>, np.nan, <span class="hljs-number">20.3</span>, np.nan, <span class="hljs-number">19.8</span>, <span class="hljs-number">20.4</span>]
    }
)
print(df)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>Now, we can use the <code>DataFrame.ffill()</code> method to fill in the missing values.</p>
<pre><code class="lang-python">ffill_df = df.ffill()
print(ffill_df)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">3</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">5</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that missing values are filled with preceding values, such as <code>24.8</code> in the second and third rows of the <code>Max Temperature</code> column and <code>29.9</code> in the fifth row of the <code>Max Temperature</code> column.</p>
<p>In the same manner, all the missing values are filled for the other two (<code>Min Temperature</code> and <code>Avg Temperature</code>) columns.</p>
<p>If you observe that the first row of <code>Min Temperature</code> remains <code>NaN</code>, it's because there was no preceding value to fill.</p>
<h3 id="heading-setting-the-limit">Setting the Limit</h3>
<p>We can also set the limit to forward fill the number of consecutive <code>NaN</code>s by specifying the <code>limit</code> parameter.</p>
<pre><code class="lang-python">limit_ffill = df.ffill(limit=<span class="hljs-number">1</span>)
print(limit_ffill)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">3</span>              NaN             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">5</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>After setting the <code>limit=1</code>, just one <code>NaN</code> value is filled in the columns <code>Max Temperature</code> and <code>Min Temperature</code> when consecutive <code>NaN</code>s were present.</p>
<h3 id="heading-limit-area">Limit Area</h3>
<p>In <strong>pandas v2.2.0</strong>, a new parameter is added called the <code>limit_area</code> which is by default set to <code>None</code>. It can be set to <code>'inside'</code> and <code>'outside'</code>.</p>
<p>It is used with the <code>limit</code> parameter and if set to</p>
<ul>
<li><p><code>None</code>: The default behavior with no restrictions. <code>NaN</code>s are filled with the last valid value, subject to any <code>limit</code> specified.</p>
</li>
<li><p><code>inside</code>: Fills only those <code>NaN</code>s that are <strong>surrounded</strong> by valid values.</p>
</li>
<li><p><code>outside</code>: Fills only those <code>NaN</code>s that are <strong>not surrounded</strong> by valid values.</p>
</li>
</ul>
<p>Using <code>ffill()</code> with <code>limit=1</code> and <code>limit_area='inside'</code></p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)

in_ffill = df.ffill(limit=<span class="hljs-number">1</span>,limit_area=<span class="hljs-string">'inside'</span>)
print(in_ffill)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">3</span>              NaN             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">5</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that <code>NaN</code> values surrounded by valid values are filled, and because the limit was set to <code>1</code>, just one <code>NaN</code> was filled from consecutive <code>NaN</code>s.</p>
<p>Using <code>ffill()</code> with <code>limit=1</code> and <code>limit_area='outside'</code></p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)

out_ffill = df.ffill(limit=<span class="hljs-number">1</span>,limit_area=<span class="hljs-string">'outside'</span>)
print(out_ffill)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>Here, we can see that dataset isn't affected at all, because all the <code>NaN</code> values are surrounded by valid values. Let's tweak the dataset and see how it affects it.</p>
<pre><code class="lang-python">df = pd.DataFrame(
    {
        <span class="hljs-string">"Max Temperature"</span>: [<span class="hljs-number">22.7</span>, <span class="hljs-number">24.8</span>, np.nan, np.nan, <span class="hljs-number">29.9</span>, <span class="hljs-number">45</span>, np.nan],
        <span class="hljs-string">"Min Temperature"</span>: [np.nan, <span class="hljs-number">20.1</span>, <span class="hljs-number">18.4</span>, np.nan, np.nan, np.nan, <span class="hljs-number">15.5</span>],
        <span class="hljs-string">"Avg Temperature"</span>: [<span class="hljs-number">21.4</span>, <span class="hljs-number">23.5</span>, np.nan, <span class="hljs-number">20.3</span>, np.nan, <span class="hljs-number">19.8</span>, np.nan]
    }
)
print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
out_ffill = df.ffill(limit=<span class="hljs-number">1</span>,limit_area=<span class="hljs-string">'outside'</span>)
print(out_ffill)
</code></pre>
<p>If we run this, we'll get this output.</p>
<pre><code class="lang-bash">Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
0             22.7              NaN             21.4
1             24.8             20.1             23.5
2              NaN             18.4              NaN
3              NaN              NaN             20.3
4             29.9              NaN              NaN
5             45.0              NaN             19.8
6              NaN             15.5              NaN
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
0             22.7              NaN             21.4
1             24.8             20.1             23.5
2              NaN             18.4              NaN
3              NaN              NaN             20.3
4             29.9              NaN              NaN
5             45.0              NaN             19.8
6             45.0             15.5             19.8
</code></pre>
<p>Notice that in our original dataset (<code>df</code>), we kept <code>NaN</code> values in the seventh row of <code>Max Temperature</code> and <code>Avg Temperature</code>.</p>
<p>When we used <code>df.ffill(limit=1,limit_area='outside')</code>, the newly added <code>NaN</code> values were filled because they were not surrounded by valid values.</p>
<h3 id="heading-filling-missing-values-across-the-axis">Filling Missing Values Across the Axis</h3>
<p>By specifying the <code>axis</code> parameter, we can control how the missing data should be filled in.</p>
<p><strong>If the axis is set to</strong> <code>0</code> or <code>'index'</code>, the missing values will be filled down each column, moving vertically (<strong>from above</strong>) along the rows. This means the last valid value from <strong>above</strong> (<strong>in the same column</strong>) will be used to fill in the <code>NaN</code> values <strong>below</strong> it.</p>
<pre><code class="lang-python">row_ffill = df.ffill(axis=<span class="hljs-number">0</span>)
print(row_ffill)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">3</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">5</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>Every <code>NaN</code> value is filled in each column moving along the row (<strong>vertically</strong>). So we can say that this is the <strong>default</strong> operation.</p>
<p><strong>If the axis is set to</strong> <code>1</code> or <code>'columns'</code>, the missing values will be filled across each row, moving horizontally (<strong>from left to right</strong>) along the columns. This means the last valid value from the <strong>left</strong> (<strong>in the same row</strong>) will be used to fill in the <code>NaN</code> values to the <strong>right</strong> of it.</p>
<pre><code class="lang-python">col_ffill = df.ffill(axis=<span class="hljs-number">1</span>)
print(col_ffill)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>             <span class="hljs-number">18.4</span>
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">29.9</span>
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that the third row of <code>Avg Temperature</code> is filled with <code>18.4</code>, the value present left of it, and in the same manner, the fifth row of <code>Min Temperature</code> and <code>Avg Temperature</code> is filled with the value <code>29.9</code>.</p>
<h2 id="heading-dataframebfill">DataFrame.bfill()</h2>
<p>The <code>DataFrame.bfill()</code> method fills the missing or <code>NaN</code> values using the <strong>next</strong> valid value in a column or row.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

df = pd.DataFrame(
    {
        <span class="hljs-string">"Max Temperature"</span>: [<span class="hljs-number">22.7</span>, <span class="hljs-number">24.8</span>, np.nan, np.nan, <span class="hljs-number">29.9</span>, np.nan, <span class="hljs-number">45</span>],
        <span class="hljs-string">"Min Temperature"</span>: [np.nan, <span class="hljs-number">20.1</span>, <span class="hljs-number">18.4</span>, np.nan, np.nan, np.nan, <span class="hljs-number">15.5</span>],
        <span class="hljs-string">"Avg Temperature"</span>: [<span class="hljs-number">21.4</span>, <span class="hljs-number">23.5</span>, np.nan, <span class="hljs-number">20.3</span>, np.nan, <span class="hljs-number">19.8</span>, <span class="hljs-number">20.4</span>]
    }
)

print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
bfill_df = df.bfill()
print(bfill_df)
</code></pre>
<p>We have a dataset (<code>df</code>) and we are filling the <code>NaN</code>s using the <code>bfill()</code> (<strong>backward filling</strong>).</p>
<pre><code class="lang-bash">Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
0             22.7              NaN             21.4
1             24.8             20.1             23.5
2              NaN             18.4              NaN
3              NaN              NaN             20.3
4             29.9              NaN              NaN
5              NaN              NaN             19.8
6             45.0             15.5             20.4
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
0             22.7             20.1             21.4
1             24.8             20.1             23.5
2             29.9             18.4             20.3
3             29.9             15.5             20.3
4             29.9             15.5             19.8
5             45.0             15.5             19.8
6             45.0             15.5             20.4
</code></pre>
<p>We can see that the <code>NaN</code> values are filled with the next values, such as <code>45.0</code> and <code>29.9</code> in the <code>Max Temperature</code> column. In the same manner, all the <code>NaN</code> values are filled.</p>
<p>Notice that in the first row of <code>Min Temperature</code>, the <code>NaN</code> value gets filled.</p>
<h3 id="heading-setting-the-limit-1">Setting the Limit</h3>
<p>The <code>DataFrame.bfill()</code> method also has the <code>limit</code> parameter to limit the number of consecutive <code>NaN</code> values filling backward.</p>
<pre><code class="lang-python">bfill_df = df.bfill(limit=<span class="hljs-number">1</span>)
print(bfill_df)
--------------------
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">3</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">5</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>In the above code, the <code>limit</code> parameter is set to <code>1</code> so only one <code>NaN</code> value was filled when consecutive <code>NaN</code>s were present.</p>
<h3 id="heading-limit-area-1">Limit Area</h3>
<p>The <code>limit_area</code> parameter in <code>DataFrame.bfill()</code> method is the same as the <code>DataFrame.ffill()</code>'s <code>limit_area</code> parameter.</p>
<p>It is used with the <code>limit</code> parameter and if set to</p>
<ul>
<li><p><code>None</code>: The default behavior with no restrictions. <code>NaN</code>s are filled with the last valid value, subject to any <code>limit</code> specified.</p>
</li>
<li><p><code>inside</code>: Fills only those <code>NaN</code>s that are surrounded by valid values.</p>
</li>
<li><p><code>outside</code>: Fills only those <code>NaN</code>s that are not surrounded by valid values.</p>
</li>
</ul>
<p>Using <code>bfill()</code> with <code>limit=1</code> and <code>limit_area='inside'</code></p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
bfill_df = df.bfill(limit=<span class="hljs-number">1</span>, limit_area=<span class="hljs-string">'inside'</span>)
print(bfill_df)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">3</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">5</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that the <code>NaN</code> surrounded by the valid values gets filled and since the limit was set to <code>1</code>, just one <code>NaN</code> gets filled when consecutive <code>NaN</code>s were present.</p>
<p>Using <code>bfill()</code> with <code>limit=1</code> and <code>limit_area='outside'</code></p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
bfill_df = df.bfill(limit=<span class="hljs-number">1</span>, limit_area=<span class="hljs-string">'outside'</span>)
print(bfill_df)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that in the first row of <code>Min Temperature</code> column, the <code>NaN</code> value was filled because that <code>NaN</code> wasn't surrounded by the valid value.</p>
<h3 id="heading-filling-missing-values-across-the-axis-1">Filling Missing Values Across the Axis</h3>
<p>We can use <code>axis</code> parameter to fill in missing values along the column or row.</p>
<p><strong>If the axis is set to</strong> <code>0</code> or <code>'index'</code>, the missing values will be filled down each column, moving vertically (<strong>from below)</strong> along the rows. This means the last valid value from <strong>below</strong> (in the same column) will be used to fill in the <code>NaN</code> values <strong>above</strong> it.</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
bfill_df = df.bfill(axis=<span class="hljs-number">0</span>)
print(bfill_df)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">3</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">5</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>It's like using the <code>bfill()</code> method without any parameters. The <code>NaN</code> values were filled vertically from below along the rows in each column.</p>
<p><strong>If the axis is set to</strong> <code>1</code> or <code>'columns'</code>, the missing values will be filled across each row, moving horizontally (<strong>from right to left</strong>) along the columns. This means the last valid value from the <strong>right</strong> (in the same row) will be used to fill in the <code>NaN</code> values to the <strong>left</strong> of it.</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Original Dataset"</span>)
print(df)
print(<span class="hljs-string">"*"</span>*<span class="hljs-number">55</span>)
bfill_df = df.bfill(axis=<span class="hljs-number">1</span>)
print(bfill_df)
--------------------
Original Dataset
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>              NaN             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>              NaN             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>              NaN              NaN             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>              NaN              NaN             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
*******************************************************
   Max Temperature  Min Temperature  Avg Temperature
<span class="hljs-number">0</span>             <span class="hljs-number">22.7</span>             <span class="hljs-number">21.4</span>             <span class="hljs-number">21.4</span>
<span class="hljs-number">1</span>             <span class="hljs-number">24.8</span>             <span class="hljs-number">20.1</span>             <span class="hljs-number">23.5</span>
<span class="hljs-number">2</span>             <span class="hljs-number">18.4</span>             <span class="hljs-number">18.4</span>              NaN
<span class="hljs-number">3</span>             <span class="hljs-number">20.3</span>             <span class="hljs-number">20.3</span>             <span class="hljs-number">20.3</span>
<span class="hljs-number">4</span>             <span class="hljs-number">29.9</span>              NaN              NaN
<span class="hljs-number">5</span>             <span class="hljs-number">19.8</span>             <span class="hljs-number">19.8</span>             <span class="hljs-number">19.8</span>
<span class="hljs-number">6</span>             <span class="hljs-number">45.0</span>             <span class="hljs-number">15.5</span>             <span class="hljs-number">20.4</span>
</code></pre>
<p>We can see that the third row of <code>Max Temperature</code> column gets filled by the value to its left (<code>18.4</code>), and the fourth and sixth rows of <code>Max Temperature</code> and <code>Min Temperature</code> get filled by the value to its left (<code>20.3</code> and <code>19.8</code>).</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/multiple-datasets-integration-using-pandas">Merge, combine, and concatenate multiple datasets using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-duplicate-rows-from-dataset">Find and delete duplicate rows from the dataset using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/copy-on-write-in-pandas">How to efficiently manage memory use when working with large datasets in pandas</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas">How to find and delete mismatched columns from datasets in pandas</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/render-images-from-flask">Upload and display images on the frontend using Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[How to Disable GIL in Python 3.13?]]></title><description><![CDATA[The Python organization has released the official version of Python 3.13, which includes many major changes.
One of the major changes we get is making GIL (Global Interpreter Lock) optional in Python 3.13.
In this article, you’ll see how to disable G...]]></description><link>https://teamgeek.geekpython.in/how-to-disable-gil-in-python-313</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-disable-gil-in-python-313</guid><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Wed, 23 Oct 2024 09:08:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728566793671/44cc4b51-c3b9-4d29-9032-716b4d719951.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The Python organization has released the official version of Python 3.13, which includes many major changes.</p>
<p>One of the major changes we get is making <strong>GIL</strong> (Global Interpreter Lock) optional in Python 3.13.</p>
<p>In this article, you’ll see how to disable GIL in Python 3.13 to make multi-threaded programs faster.</p>
<h1 id="heading-disable-gil-in-python-313">Disable GIL in Python 3.13</h1>
<p>First, <a target="_blank" href="https://www.python.org/ftp/python/3.13.0/python-3.13.0-amd64.exe">download</a> the official Python 3.13 on your local machine. Then proceed to install the Python executable file.</p>
<p>Follow the steps just as you install any Python version, you will see a step in which you are asked to choose the advanced installation options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728558748632/8a045d7a-aa69-4840-8467-33997961ce80.png" alt="Advance free-threaded option" class="image--center mx-auto" /></p>
<p>Now select the checkbox appearing at the end, this will install the different executable Python build with the name <code>python3.13t</code> or <code>python3.13t.exe</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728559580980/addaff3f-87da-49f2-a4e9-79d6ec3fcfd7.png" alt="Enable free-threaded option" class="image--center mx-auto" /></p>
<p>This will allow you to optionally disable or enable GIL in the runtime. Now proceed to install the setup.</p>
<p>After completing the setup for Python 3.13, if you look at the file location of Python 3.13, you will see that you also got a different Python build called <code>python3.13t</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728564173200/388c716e-4885-4626-9ab3-68fca4155326.png" alt="Free-threaded CPython" class="image--center mx-auto" /></p>
<p>If you remember that <strong>“free-threaded binaries”</strong> mode was marked <strong>“experimental”</strong>, this means that you don’t get GIL disabled by default.</p>
<p><strong>But how do I disable GIL? Python organization provided a different CPython build which is also called “Free-threaded CPython”.</strong></p>
<p><strong>Free-threaded CPython</strong> will help you <strong>disable GIL</strong>. Let’s see how to do it.</p>
<p>Let’s say, you have a Python script and you want it to run with GIL disabled. You can use the following command.</p>
<pre><code class="lang-bash">python3.13t main.py
</code></pre>
<p><strong>This CPython build comes with GIL disabled by default</strong>.</p>
<h2 id="heading-practical">Practical</h2>
<p>I have the following Python script (<code>main.py</code>) that runs a multi-threaded task and calculates the time taken to complete the execution.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> sysconfig
<span class="hljs-keyword">import</span> math
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> threading

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">compute_factorial</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">return</span> math.factorial(n)

<span class="hljs-comment"># Multi-threaded</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multi_threaded_compute</span>(<span class="hljs-params">n</span>):</span>
    threads = []
    <span class="hljs-comment"># Create 5 threads</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> n:
        thread = threading.Thread(target=compute_factorial, args=(num,))
        threads.append(thread)
        thread.start()

    <span class="hljs-comment"># Wait for all threads to complete</span>
    <span class="hljs-keyword">for</span> thread <span class="hljs-keyword">in</span> threads:
        thread.join()

    print(<span class="hljs-string">"Factorial Computed."</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-comment"># Checking Version</span>
    print(<span class="hljs-string">f"Python version: <span class="hljs-subst">{sys.version}</span>"</span>)

    <span class="hljs-comment"># GIL Status</span>
    status = sysconfig.get_config_var(<span class="hljs-string">"Py_GIL_DISABLED"</span>)
    <span class="hljs-keyword">if</span> status <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        print(<span class="hljs-string">"GIL cannot be disabled"</span>)
    <span class="hljs-keyword">if</span> status == <span class="hljs-number">0</span>:
        print(<span class="hljs-string">"GIL is active"</span>)
    <span class="hljs-keyword">if</span> status == <span class="hljs-number">1</span>:
        print(<span class="hljs-string">"GIL is disabled"</span>)

    numlist = [<span class="hljs-number">100000</span>, <span class="hljs-number">200000</span>, <span class="hljs-number">300000</span>, <span class="hljs-number">400000</span>, <span class="hljs-number">500000</span>]

    <span class="hljs-comment"># Multi-threaded Execution</span>
    start = time.time()
    multi_threaded_compute(numlist)
    end = time.time() - start
    print(<span class="hljs-string">f"Time taken : <span class="hljs-subst">{end:<span class="hljs-number">.2</span>f}</span> seconds"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>Now, we’ll run this script with and without free-threaded CPython.</p>
<p><strong>With GIL enable (without free-threaded CPython)</strong></p>
<pre><code class="lang-bash">python main.py
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728566000462/0c5becba-d7d9-4c7c-96a5-00b52c855fe6.png" alt="Python running with GIL enabled" class="image--center mx-auto" /></p>
<p><strong>With GIL disable (with free-threaded CPython)</strong></p>
<pre><code class="lang-bash">python3.13t main.py
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728566083471/08f68d34-4a6d-4940-aa74-9b3c431efdde.png" alt="Python running with GIL disabled" class="image--center mx-auto" /></p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[How To Install Redis on Windows Successfully?]]></title><description><![CDATA[Redis is an in-memory database that actually makes it the fastest among all the databases.
What does "in-memory" mean? It means that it stores the data in temporary memory or RAM, in the form of key-value pairs. This makes it perfect for serving resu...]]></description><link>https://teamgeek.geekpython.in/how-to-install-redis-on-windows-successfully</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-to-install-redis-on-windows-successfully</guid><category><![CDATA[Redis]]></category><category><![CDATA[Databases]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Sat, 12 Oct 2024 06:30:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728552546263/ebec68b8-d40e-4dc9-8dfc-cde2147b07fd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Redis is an in-memory database that actually makes it the fastest among all the databases.</p>
<p>What does <strong>"in-memory"</strong> mean? It means that it stores the data in temporary memory or RAM, in the form of key-value pairs. This makes it perfect for serving results instantly.</p>
<p>In this article, you’ll learn how to install Redis locally on Windows without any hassle.</p>
<h1 id="heading-installation-process-begins">Installation Process Begins</h1>
<p>You probably don’t know that Redis isn’t officially available for Windows yet but there is a way that you can install <strong>Redis locally on Windows</strong> and get started with it.</p>
<p>Redis is available for MacOS, Linux but for Windows, they say:</p>
<blockquote>
<p>Redis is not officially supported on Windows. However, you can install Redis on Windows for development.</p>
</blockquote>
<p><strong>So, how to install it then?</strong> Simple, actually not simple in my opinion but I will guide you step by step installing Redis on your Windows machine.</p>
<h2 id="heading-enable-wsl-on-windows">Enable WSL on Windows</h2>
<p>To install Redis on Windows, you need to enable <strong>WSL</strong> (Windows Subsystem for Linux). It simply means that you need to install Linux on your Windows system.</p>
<p><strong>To enable WSL, you must be running Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11.</strong></p>
<p>You can enable the <strong>WSL2</strong> (WSL version 2) by default with a single command.</p>
<p>Open Powershell in administrator mode and run the following command.</p>
<pre><code class="lang-bash">wsl --install
</code></pre>
<p>This command will enable the features necessary to run WSL and install the Ubuntu distribution of Linux.</p>
<p>You can change or install another distribution of Linux if you want to, just use the following command.</p>
<pre><code class="lang-bash">wsl --install -d &lt;Distribution Name&gt;
</code></pre>
<p>You can replace &lt;Distribution Name&gt; with the actual Linux distribution you want to install on the Windows machine. But, I would recommend keeping the default settings.</p>
<p>After all this installation process, restart your Windows machine once to see the changes.</p>
<p>If your Windows machine is a bit older and WSL2 is not supported then <a target="_blank" href="https://learn.microsoft.com/en-us/windows/wsl/install-manual">check out this guide</a> from Microsoft itself to <strong>manually enable WSL on Windows</strong>.</p>
<h2 id="heading-troubleshooting-error">Troubleshooting Error</h2>
<p>There will be less chance that you will get errors while setting up WSL but in case you encounter any error such as “<strong>failed to register wsl distribution</strong>” or something like that then <strong>consider changing the WSL version</strong>.</p>
<p>Run the following command in Powershell in administrator mode to change the version of your WSL.</p>
<pre><code class="lang-bash">wsl --set-default-version 1
</code></pre>
<p>This command will <strong>change the default version</strong> which is WSL2 to WSL1. This will solve most of the problems.</p>
<p>Now, restart your Windows machine again to see the effect.</p>
<h2 id="heading-set-up-linux">Set Up Linux</h2>
<p>After enabling WSL and installing Linux distribution, you need to set up user info for Linux.</p>
<p>Open Ubuntu or whichever distribution you installed and give it a few minutes to install. After that, it will ask you to enter a username for Linux and set a password.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728549471374/c6c86f8c-be17-440b-be9e-f92234995926.png" alt="Creating Linux user account" class="image--center mx-auto" /></p>
<p>After setting up the Linux distribution, the next step is to install Redis.</p>
<h2 id="heading-install-redis-on-windows">Install Redis on Windows</h2>
<p>Redis can be installed on Windows using the following commands</p>
<pre><code class="lang-bash">curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg

<span class="hljs-built_in">echo</span> <span class="hljs-string">"deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb <span class="hljs-subst">$(lsb_release -cs)</span> main"</span> | sudo tee /etc/apt/sources.list.d/redis.list

sudo apt-get update
sudo apt-get install redis
</code></pre>
<p>Copy the above commands all together and paste them into the Ubuntu terminal, this will start the process of installing Redis on Windows locally.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728549923677/27fdc476-82ed-4012-a5b2-739901e06872.png" alt="Collecting Redis package" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728549938799/474ee4c0-0385-4fa6-8c9a-66d80a61e5bd.png" alt="Collecting Redis package" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728549953320/7515491c-05ea-41cb-987b-e7ab04ed0b62.png" alt="Updating" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728549974416/3c2328b3-cd4c-4a16-9f28-81b9cebe610a.png" alt="Installing Redis" class="image--center mx-auto" /></p>
<h2 id="heading-start-redis">Start Redis</h2>
<p>Now run the following command to start the Redis server.</p>
<pre><code class="lang-bash">sudo service redis-server start
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728550241527/ee2cdfc3-9312-4bd2-b58a-db10240c9cda.png" alt="Redis server" class="image--center mx-auto" /></p>
<p>Now to check if you’re connected to Redis, run the following command.</p>
<pre><code class="lang-bash">redis-cli
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728550319283/be0aa1ed-9098-4535-91af-b600466a68b9.png" alt="Redis CLI" class="image--center mx-auto" /></p>
<p>Redis server started on <strong>localhost</strong> and listening on <strong>port 6379</strong> which is its default port.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Enabling Copy on Write in Pandas for Efficient Memory Management]]></title><description><![CDATA[Pandas supports Copy-on-Write, an optimization technique that helps improve memory use, particularly when working with large datasets.
Starting from version 2.0 of Pandas, the Copy-on-Write (CoW) has taken effect but has not been fully implemented. M...]]></description><link>https://teamgeek.geekpython.in/enabling-copy-on-write-in-pandas</link><guid isPermaLink="true">https://teamgeek.geekpython.in/enabling-copy-on-write-in-pandas</guid><category><![CDATA[pandas]]></category><category><![CDATA[Machine Learning]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 10 Oct 2024 10:00:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723225477775/d0d45821-fc3a-4be0-890d-15c43860cc78.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Pandas supports Copy-on-Write, an optimization technique that helps improve memory use, particularly when working with large datasets.</p>
<p>Starting from version 2.0 of Pandas, the Copy-on-Write (CoW) has taken effect but has not been fully implemented. Most of the optimizations that are possible through Copy-on-Write are supported.</p>
<h2 id="heading-aim-of-copy-on-write">Aim of Copy-on-Write</h2>
<p>As the name suggests, the data will be copied when it is modified. What it means?</p>
<p>When a DataFrame or Series shares the same data as the original, it will initially share the same memory for the data rather than creating a copy. When the data of either the original or new DataFrame is modified, a new copy of the data is created for the DataFrame that is being modified.</p>
<p>This will efficiently save memory usage and improve performance when working with large datasets.</p>
<h2 id="heading-enabling-cow-in-pandas">Enabling CoW in Pandas</h2>
<p>It is not enabled by default, so we need to enable it using the <code>copy_on_write</code> configuration option in Pandas.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Option1</span>
pd.options.mode.copy_on_write = <span class="hljs-literal">True</span>
<span class="hljs-comment"># Option2</span>
pd.set_option(<span class="hljs-string">"mode.copy_on_write"</span> : <span class="hljs-literal">True</span>)
</code></pre>
<p>You can use any of the options to turn on CoW globally in your environment.</p>
<p><strong>Note: CoW will be enabled by default in Pandas 3.0, so get used to it early on.</strong></p>
<h2 id="heading-impact-of-cow-in-pandas">Impact of CoW in Pandas</h2>
<p>The CoW will disallow updating the multiple pandas objects at the same time. Here's how it will happen.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
subset = df[<span class="hljs-string">"A"</span>]
subset.iloc[<span class="hljs-number">0</span>] = <span class="hljs-number">10</span>
df
</code></pre>
<p>With CoW, the above snippet will not modify <code>df</code> rather it modifies only the data of <code>subset</code>.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># df</span>
    A    B
0    1    4
1    2    5
2    3    6

<span class="hljs-comment"># subset</span>
    A
0    10
1    2
2    3
</code></pre>
<h3 id="heading-inplace-operations-will-not-work">inplace Operations will Not Work</h3>
<p>Similarly, the <code>inplace</code> operations will not work with CoW enabled, which directly modifies the original <code>df</code>.</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
df[<span class="hljs-string">"A"</span>].replace(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>, inplace=<span class="hljs-literal">True</span>)
df
--------------------
    A    B
<span class="hljs-number">0</span>    <span class="hljs-number">1</span>    <span class="hljs-number">4</span>
<span class="hljs-number">1</span>    <span class="hljs-number">2</span>    <span class="hljs-number">5</span>
<span class="hljs-number">2</span>    <span class="hljs-number">3</span>    <span class="hljs-number">6</span>
</code></pre>
<p>We can see that <code>df</code> has remained unchanged and additionally, we will see a <code>ChainedAssignmentError</code> warning.</p>
<p>The above operation can be performed in two different ways. One method is to avoid <code>inplace</code>, and another is to use <code>inplace</code> to directly modify the original <code>df</code> at the <code>DataFrame</code> level.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Avoid inplace</span>
df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
df[<span class="hljs-string">"A"</span>] = df[<span class="hljs-string">"A"</span>].replace(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>)
df
--------------------
    A    B
<span class="hljs-number">0</span>    <span class="hljs-number">5</span>    <span class="hljs-number">4</span>
<span class="hljs-number">1</span>    <span class="hljs-number">2</span>    <span class="hljs-number">5</span>
<span class="hljs-number">2</span>    <span class="hljs-number">3</span>    <span class="hljs-number">6</span>
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># Using inplace at DataFrame level</span>
df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
df.replace({<span class="hljs-string">"A"</span>: {<span class="hljs-number">2</span>: <span class="hljs-number">34</span>}}, inplace=<span class="hljs-literal">True</span>)
df
--------------------
    A    B
<span class="hljs-number">0</span>    <span class="hljs-number">1</span>    <span class="hljs-number">4</span>
<span class="hljs-number">1</span>    <span class="hljs-number">34</span>    <span class="hljs-number">5</span>
<span class="hljs-number">2</span>    <span class="hljs-number">3</span>    <span class="hljs-number">6</span>
</code></pre>
<h3 id="heading-chained-assignment-will-never-work">Chained Assignment Will Never Work</h3>
<p>When we modify the DataFrame or Series using multiple indexing operations in a single line of code, this is what we call the chained assignment technique.</p>
<pre><code class="lang-python"><span class="hljs-comment"># CoW disabled</span>
<span class="hljs-keyword">with</span> pd.option_context(<span class="hljs-string">"mode.copy_on_write"</span>, <span class="hljs-literal">False</span>):
    df = pd.DataFrame({<span class="hljs-string">"A"</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-string">"B"</span>: [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>]})
    df[<span class="hljs-string">"B"</span>][df[<span class="hljs-string">'A'</span>] &gt; <span class="hljs-number">2</span>] = <span class="hljs-number">10</span>
df
</code></pre>
<p>The above code snippet is trying to change column <code>B</code> from the original <code>df</code> where column <code>A</code> is greater than 2. It means the value at the 2nd and 3rd index in column <code>B</code> will be modified.</p>
<p>Since the CoW is disabled, this operation is allowed, and the original <code>df</code> will be modified.</p>
<pre><code class="lang-bash">    A    B
0    1    5
1    2    6
2    3    10
3    4    10
</code></pre>
<p>But, this will never work with CoW enabled in pandas.</p>
<pre><code class="lang-python"><span class="hljs-comment"># CoW enabled</span>
df = pd.DataFrame({<span class="hljs-string">"A"</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-string">"B"</span>: [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>]})
df[<span class="hljs-string">"B"</span>][df[<span class="hljs-string">"A"</span>] &gt; <span class="hljs-number">2</span>] = <span class="hljs-number">10</span>
df
--------------------
    A    B
<span class="hljs-number">0</span>    <span class="hljs-number">1</span>    <span class="hljs-number">5</span>
<span class="hljs-number">1</span>    <span class="hljs-number">2</span>    <span class="hljs-number">6</span>
<span class="hljs-number">2</span>    <span class="hljs-number">3</span>    <span class="hljs-number">7</span>
<span class="hljs-number">3</span>    <span class="hljs-number">4</span>    <span class="hljs-number">8</span>
</code></pre>
<p>Instead, with copy-on-write, we can use <code>.loc</code> to modify the <code>df</code> using multiple indexing conditions.</p>
<pre><code class="lang-python"><span class="hljs-comment"># CoW enabled</span>
df = pd.DataFrame({<span class="hljs-string">"A"</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-string">"B"</span>: [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>]})
df.loc[(df[<span class="hljs-string">"A"</span>] == <span class="hljs-number">1</span>) | (df[<span class="hljs-string">"A"</span>] &gt; <span class="hljs-number">3</span>), <span class="hljs-string">"B"</span>] = <span class="hljs-number">100</span>
df
</code></pre>
<p>This will modify column <code>B</code> where column <code>A</code> is either 1 or greater than 3. The original <code>df</code> will look like the following.</p>
<pre><code class="lang-bash">    A    B
0    1    100
1    2    6
2    3    7
3    4    100
</code></pre>
<h3 id="heading-read-only-arrays">Read-only Arrays</h3>
<p>When a Series or DataFrame is accessed as a NumPy array, that array will be read-only if the array shares the same data with the initial DataFrame or Series.</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</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-string">"B"</span>: [<span class="hljs-string">'5'</span>, <span class="hljs-string">'6'</span>, <span class="hljs-string">'7'</span>, <span class="hljs-string">'8'</span>]})
arr = df.to_numpy()
arr
--------------------
array([[<span class="hljs-number">1</span>, <span class="hljs-string">'5'</span>],
       [<span class="hljs-number">2</span>, <span class="hljs-string">'6'</span>],
       [<span class="hljs-number">3</span>, <span class="hljs-string">'7'</span>],
       [<span class="hljs-number">4</span>, <span class="hljs-string">'8'</span>]], dtype=object)
</code></pre>
<p>In the above code snippet, <code>arr</code> will be a copy because df contains two different types of arrays (<code>int</code> and <code>str</code>). We can perform modifications on the <code>arr</code>.</p>
<pre><code class="lang-python">arr[<span class="hljs-number">1</span>, <span class="hljs-number">0</span>] = <span class="hljs-number">10</span>
arr
--------------------
array([[<span class="hljs-number">1</span>, <span class="hljs-string">'5'</span>],
       [<span class="hljs-number">10</span>, <span class="hljs-string">'6'</span>],
       [<span class="hljs-number">3</span>, <span class="hljs-string">'7'</span>],
       [<span class="hljs-number">4</span>, <span class="hljs-string">'8'</span>]], dtype=object)
</code></pre>
<p>Take a look at this case.</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</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-string">"B"</span>: [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>]})
arr = df.to_numpy()
arr
</code></pre>
<p>The DataFrame <code>df</code> has only one NumPy array (array of same data types), so <code>arr</code> shares the data with <code>df</code>. This means <code>arr</code> will be read-only and cannot be modified inplace.</p>
<pre><code class="lang-python">print(arr.flags.writeable)
arr[<span class="hljs-number">0</span>,<span class="hljs-number">0</span>] = <span class="hljs-number">10</span>
arr
--------------------
<span class="hljs-literal">False</span>
ValueError: assignment destination <span class="hljs-keyword">is</span> read-only
</code></pre>
<h3 id="heading-lazy-copy-mechanism">Lazy Copy Mechanism</h3>
<p>When two or more DataFrames share the same data, the copies will not be created immediately.</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
df2 = df.reset_index(drop=<span class="hljs-literal">True</span>)
</code></pre>
<p>Both <code>df</code> and <code>df2</code> shares the same reference in the memory as both share the same data. The copy mechanism will trigger only when any of the DataFrame is modified.</p>
<pre><code class="lang-python">df2.iloc[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>] = <span class="hljs-number">10</span>
print(df2)
print(df)
--------------------
    A  B
<span class="hljs-number">0</span>  <span class="hljs-number">10</span>  <span class="hljs-number">4</span>
<span class="hljs-number">1</span>   <span class="hljs-number">2</span>  <span class="hljs-number">5</span>
<span class="hljs-number">2</span>   <span class="hljs-number">3</span>  <span class="hljs-number">6</span>
   A  B
<span class="hljs-number">0</span>  <span class="hljs-number">1</span>  <span class="hljs-number">4</span>
<span class="hljs-number">1</span>  <span class="hljs-number">2</span>  <span class="hljs-number">5</span>
<span class="hljs-number">2</span>  <span class="hljs-number">3</span>  <span class="hljs-number">6</span>
</code></pre>
<p>But this is not necessary, if we don't want initial <code>df</code>, we can simply reassign it to the same variable (<code>df</code>) and this process will create a new reference. This will avoid the copy-on-write process.</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
print(<span class="hljs-string">"Initial reference: "</span>,id(df))
df = df.reset_index(drop=<span class="hljs-literal">True</span>)
print(<span class="hljs-string">"New reference: "</span>,id(df))
df.iloc[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>] = <span class="hljs-number">10</span>
print(df)
--------------------
Initial reference:  <span class="hljs-number">138400246865760</span>
New reference:      <span class="hljs-number">138400246860336</span>
    A  B
<span class="hljs-number">0</span>  <span class="hljs-number">10</span>  <span class="hljs-number">4</span>
<span class="hljs-number">1</span>   <span class="hljs-number">2</span>  <span class="hljs-number">5</span>
<span class="hljs-number">2</span>   <span class="hljs-number">3</span>  <span class="hljs-number">6</span>
</code></pre>
<p>This same optimization (lazy copy mechanism) is added to the methods that don't require a copy of the original data.</p>
<p><strong>DataFrame.rename()</strong></p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]})
df.rename(columns={<span class="hljs-string">"A"</span>: <span class="hljs-string">"X"</span>, <span class="hljs-string">"B"</span>: <span class="hljs-string">"Y"</span>})
--------------------
    X    Y
<span class="hljs-number">0</span>    <span class="hljs-number">1</span>    <span class="hljs-number">4</span>
<span class="hljs-number">1</span>    <span class="hljs-number">2</span>    <span class="hljs-number">5</span>
<span class="hljs-number">2</span>    <span class="hljs-number">3</span>    <span class="hljs-number">6</span>
</code></pre>
<p>When CoW is enabled, this method returns the original DataFrame rather than creating an entire copy of the data, unlike the regular execution.</p>
<p><strong>DataFrame.drop() for axis=1</strong></p>
<p>Similarly, the same mechanism is implemented for <code>DataFrame.drop()</code> for <code>axis=1</code> (<code>axis='columns'</code>).</p>
<pre><code class="lang-python">df = pd.DataFrame({<span class="hljs-string">"A"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], <span class="hljs-string">"C"</span>: [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>]})
df.drop([<span class="hljs-string">"A"</span>], axis=<span class="hljs-number">1</span>)
--------------------
    B    C
<span class="hljs-number">0</span>    <span class="hljs-number">4</span>    <span class="hljs-number">7</span>
<span class="hljs-number">1</span>    <span class="hljs-number">5</span>    <span class="hljs-number">8</span>
<span class="hljs-number">2</span>    <span class="hljs-number">6</span>    <span class="hljs-number">9</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Pandas will by default implement Copy-on-Write (CoW) in version 3.0. All these optimizations that are compliant with CoW will lead to efficient memory and resource management when working with large datasets.</p>
<p>This will reduce unpredictable or inconsistent behavior and greatly maximize performance.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/multiple-datasets-integration-using-pandas">Merge, combine, and concatenate multiple datasets using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-duplicate-rows-from-dataset">Find and delete duplicate rows from the dataset using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas">Find and Delete Mismatched Columns From DataFrames Using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/tempfile-in-python">Create temporary files and directories using tempfile module in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/render-images-from-flask">Upload and display images on the frontend using Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[3 Methods to Handle Missing Values in Dataset Using Pandas]]></title><description><![CDATA[Pandas provide numerous functions and methods to clean and preprocess the dataset to make it production-ready.
In this article, we'll see the methods provided by pandas to handle missing values in a dataset.
df.fillna()
The DataFrame.fillna() is used...]]></description><link>https://teamgeek.geekpython.in/3-methods-to-handle-missing-values-in-dataset-using-pandas</link><guid isPermaLink="true">https://teamgeek.geekpython.in/3-methods-to-handle-missing-values-in-dataset-using-pandas</guid><category><![CDATA[pandas]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 19 Sep 2024 17:14:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724783806110/bf2c2f5f-3116-4086-b5ef-72a829eb9dbf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Pandas provide numerous functions and methods to clean and preprocess the dataset to make it production-ready.</p>
<p>In this article, we'll see the methods provided by pandas to <strong>handle missing values</strong> in a dataset.</p>
<h2 id="heading-dffillna">df.fillna()</h2>
<p>The <a target="_blank" href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html"><code>DataFrame.fillna()</code></a> is used to fill in the missing values with the desired value. Let's see how we can use it.</p>
<pre><code class="lang-python">data = {<span class="hljs-string">"A"</span>: [<span class="hljs-number">2</span>, np.nan, <span class="hljs-number">19</span>, <span class="hljs-number">34</span>, np.nan],
        <span class="hljs-string">"B"</span>: [np.nan, <span class="hljs-number">23</span>, <span class="hljs-number">12</span>, <span class="hljs-number">34</span>, np.nan]}
df = pd.DataFrame(data)
df
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>   NaN
<span class="hljs-number">1</span>   NaN  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>   NaN   NaN
</code></pre>
<h3 id="heading-filling-arbitrary-value">Filling Arbitrary Value</h3>
<pre><code class="lang-python">filled_df = df.fillna(<span class="hljs-number">0</span>)
print(filled_df)
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>   <span class="hljs-number">0.0</span>
<span class="hljs-number">1</span>   <span class="hljs-number">0.0</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>   <span class="hljs-number">0.0</span>   <span class="hljs-number">0.0</span>
</code></pre>
<p>We passed an arbitrary value (<code>0</code>) to fill those <code>NaN</code> values in the dataset <code>df</code>.</p>
<h3 id="heading-fill-using-a-dataset">Fill Using a Dataset</h3>
<p>We can also use a dataset to fill in the missing values.</p>
<pre><code class="lang-python">df2 = pd.DataFrame({<span class="hljs-string">"A"</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>], <span class="hljs-string">"B"</span>: [<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>]})
fill_using_df = df.fillna(df2)
print(fill_using_df)
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>   <span class="hljs-number">6.0</span>
<span class="hljs-number">1</span>   <span class="hljs-number">2.0</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>   <span class="hljs-number">5.0</span>  <span class="hljs-number">10.0</span>
</code></pre>
<p>When using the <code>fillna()</code> method with <code>df2</code>, the <code>NaN</code> values in the original DataFrame <code>df</code> are replaced by the corresponding values in <code>df2</code>. If a cell in <code>df</code> is <code>NaN</code>, the method will look for the corresponding value in <code>df2</code> (at the same position) and use that value to fill in the <code>NaN</code>.</p>
<h3 id="heading-filling-different-values-in-each-column">Filling Different Values in Each Column</h3>
<p>If we want to fill in different values in each column, we can use the following approach.</p>
<pre><code class="lang-python">values = {<span class="hljs-string">"A"</span>: <span class="hljs-number">100</span>, <span class="hljs-string">"B"</span>: <span class="hljs-number">200</span>}
diff_val = df.fillna(value=values)
print(diff_val)
--------------------
       A      B
<span class="hljs-number">0</span>    <span class="hljs-number">2.0</span>  <span class="hljs-number">200.0</span>
<span class="hljs-number">1</span>  <span class="hljs-number">100.0</span>   <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>   <span class="hljs-number">19.0</span>   <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>   <span class="hljs-number">34.0</span>   <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>  <span class="hljs-number">100.0</span>  <span class="hljs-number">200.0</span>
</code></pre>
<p>The value dictionary holds values to fill <code>NaN</code> in columns <code>A</code> and <code>B</code> in the dataset. By using <code>df.fillna(value=values)</code>, the <code>NaN</code> value in column <code>A</code> is filled with the value <code>100</code> and <code>NaN</code> value in column <code>B</code> is filled with the value <code>200</code>.</p>
<h2 id="heading-dfinterpolate">df.interpolate()</h2>
<p>The <a target="_blank" href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.interpolate.html"><code>DataFrame.interpolate()</code></a> method provides various <strong>interpolation techniques</strong> to fill in the missing values.</p>
<p>Instead of filling in hard-coded values, we can use an interpolation method to fill missing values that make the dataset even more expressive and real.</p>
<h3 id="heading-filling-computed-value">Filling Computed Value</h3>
<pre><code class="lang-python">df2 = df.interpolate()  <span class="hljs-comment"># default: linear method and axis=0</span>
print(df2)
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>   NaN
<span class="hljs-number">1</span>  <span class="hljs-number">10.5</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
</code></pre>
<p>When we use <code>df.interpolate()</code>, the default <code>linear</code> interpolation method is used that fills the <code>NaN</code> values equally spaced ignoring the index.</p>
<p>For example, in column <code>A</code>, <code>10.5</code> is filled which is equally spaced between the values <code>2.0</code> and <code>19.0</code> with the difference of <code>8.5</code>.</p>
<p>But if we see the fourth row in both columns, they are filled with the same value (<code>34.0</code>) as above them because there were no values to compute in the fifth row.</p>
<h3 id="heading-filling-nearest-values">Filling Nearest Values</h3>
<pre><code class="lang-python">data = {<span class="hljs-string">"A"</span>: [<span class="hljs-number">3</span>, np.nan, <span class="hljs-number">2</span>, np.nan, <span class="hljs-number">4</span>],
        <span class="hljs-string">"B"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">4</span>, np.nan, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>]}
df = pd.DataFrame(data)
df3= df.interpolate(method=<span class="hljs-string">'nearest'</span>)
print(df3)
--------------------
     A    B
<span class="hljs-number">0</span>  <span class="hljs-number">3.0</span>  <span class="hljs-number">1.0</span>
<span class="hljs-number">1</span>  <span class="hljs-number">3.0</span>  <span class="hljs-number">4.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">2.0</span>  <span class="hljs-number">4.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">2.0</span>  <span class="hljs-number">2.0</span>
<span class="hljs-number">4</span>  <span class="hljs-number">4.0</span>  <span class="hljs-number">5.0</span>
</code></pre>
<p>When we use <code>method='nearest'</code>, the <code>NaN</code> values are filled with the nearest valid values.</p>
<p>In this case, the second row in column <code>A</code> is filled with the value of <code>3.0</code>. <strong>Why so?</strong> The nearest value is decided based on the index close to the <code>NaN</code> value index. The index <code>0</code> (<code>3.0</code>) is closest to the index <code>1</code>. The same is applied to all the <code>NaN</code> values.</p>
<h3 id="heading-filling-values-considering-index-values">Filling Values Considering Index Values</h3>
<pre><code class="lang-python">data = {<span class="hljs-string">"A"</span>: [<span class="hljs-number">3</span>, np.nan, <span class="hljs-number">9</span>, np.nan, <span class="hljs-number">4</span>],
        <span class="hljs-string">"B"</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">10</span>, np.nan, <span class="hljs-number">20</span>, <span class="hljs-number">5</span>]}
df = pd.DataFrame(data)
df4= df.interpolate(method=<span class="hljs-string">'values'</span>)  <span class="hljs-comment"># or method='index'</span>
print(df4)
--------------------
     A     B
<span class="hljs-number">0</span>  <span class="hljs-number">3.0</span>   <span class="hljs-number">1.0</span>
<span class="hljs-number">1</span>  <span class="hljs-number">6.0</span>  <span class="hljs-number">10.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">9.0</span>  <span class="hljs-number">15.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">6.5</span>  <span class="hljs-number">20.0</span>
<span class="hljs-number">4</span>  <span class="hljs-number">4.0</span>   <span class="hljs-number">5.0</span>
</code></pre>
<p>The <code>NaN</code> values are filled equally spaced considering the values of the index surrounding the <code>NaN</code> value index.</p>
<h2 id="heading-dfffill-and-dfbfill">df.ffill() and df.bfill()</h2>
<p>The <a target="_blank" href="https://geekpython.in/ffill-and-bfill-in-pandas"><code>DataFrame.ffill()</code></a> method is used to fill the <strong>last</strong> valid value in the missing place whereas the <a target="_blank" href="https://geekpython.in/ffill-and-bfill-in-pandas"><code>DataFrame.bfill()</code></a> method is used to fill the <strong>next</strong> valid value.</p>
<h3 id="heading-forward-filling-with-ffill">Forward Filling With ffill()</h3>
<pre><code class="lang-python">data = {<span class="hljs-string">"A"</span>: [<span class="hljs-number">2</span>, np.nan, <span class="hljs-number">19</span>, <span class="hljs-number">34</span>, np.nan],
        <span class="hljs-string">"B"</span>: [np.nan, <span class="hljs-number">23</span>, <span class="hljs-number">12</span>, <span class="hljs-number">34</span>, np.nan]}
df = pd.DataFrame(data)

forward_fill = df.ffill()
print(forward_fill)
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>   NaN
<span class="hljs-number">1</span>   <span class="hljs-number">2.0</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
</code></pre>
<p>We can see that <code>NaN</code> values are filled with the preceding valid values, for instance, the second row of column <code>A</code> is filled with <code>2.0</code> which is the same value above it.</p>
<h3 id="heading-backward-filling-with-bfill">Backward Filling With bfill()</h3>
<pre><code class="lang-python">data = {<span class="hljs-string">"A"</span>: [<span class="hljs-number">2</span>, np.nan, <span class="hljs-number">19</span>, <span class="hljs-number">34</span>, np.nan],
        <span class="hljs-string">"B"</span>: [np.nan, <span class="hljs-number">23</span>, <span class="hljs-number">12</span>, <span class="hljs-number">34</span>, np.nan]}
df = pd.DataFrame(data)

backward_fill = df.bfill()
print(backward_fill)
--------------------
      A     B
<span class="hljs-number">0</span>   <span class="hljs-number">2.0</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">1</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">23.0</span>
<span class="hljs-number">2</span>  <span class="hljs-number">19.0</span>  <span class="hljs-number">12.0</span>
<span class="hljs-number">3</span>  <span class="hljs-number">34.0</span>  <span class="hljs-number">34.0</span>
<span class="hljs-number">4</span>   NaN   NaN
</code></pre>
<p>In this case, the <code>NaN</code> is filled with the next valid values, for instance, the first row of column <code>B</code> is filled with <code>23.0</code> which is the next value in the column.</p>
<p>We can also see that the fifth row of columns <code>A</code> and <code>B</code> remains unfilled (<code>NaN</code>) due to the absence of the next valid value in the dataset.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/ffill-and-bfill-in-pandas">Pandas df.ffill() and df.bfill() to handle missing values</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/multiple-datasets-integration-using-pandas">Merge, combine, and concatenate multiple datasets using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-duplicate-rows-from-dataset">Find and delete duplicate rows from the dataset using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/copy-on-write-in-pandas">How to efficiently manage memory use when working with large datasets in pandas</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas">How to find and delete mismatched columns from datasets in pandas</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[How Much SQL You Should Know for a Data Science Role]]></title><description><![CDATA[If you are applying for data science roles, it is essential to have a solid understanding of key SQL topics and concepts.
Data retrieval and manipulation are critical skills for both Data Scientists and Data Analysts, as they form the foundation for ...]]></description><link>https://teamgeek.geekpython.in/how-much-sql-you-should-know-for-a-data-science-role</link><guid isPermaLink="true">https://teamgeek.geekpython.in/how-much-sql-you-should-know-for-a-data-science-role</guid><category><![CDATA[SQL]]></category><category><![CDATA[Data Science]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 19 Sep 2024 16:14:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726760620109/cc7b273c-5260-4a1b-9f96-369038648e8d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>If you are applying for data science roles, it is essential to have a solid understanding of key SQL topics and concepts.</strong></p>
<p>Data retrieval and manipulation are critical skills for both Data Scientists and Data Analysts, as they form the foundation for effective data analysis.</p>
<p>Below are the SQL topics and concepts, prioritized from highest to lowest, that a data scientist should be proficient in.</p>
<h1 id="heading-1-sql-querying">1. SQL Querying</h1>
<p>A strong foundation in <strong>SQL</strong> is crucial for data scientists, as it forms the basis for building efficient and effective data analysis processes. Proficiency in basic SQL querying, along with the ability to write complex yet readable and manageable queries, is essential. If you're not familiar with constructing queries or using the right commands, you risk facing constant challenges in your data tasks.</p>
<h1 id="heading-2-sql-joins">2. SQL Joins</h1>
<p><strong>SQL joins</strong> are a crucial concept for data scientists. In real-world scenarios, you rarely work with data from a single table. Instead, databases contain data from multiple sources, fields, or departments - often spread across different tables. These datasets contribute to various aspects of business growth, and as a data scientist, you need to combine and analyze them effectively.</p>
<p>For instance, if your organization is in the book business, you might have separate tables for members, books, orders, and more. To provide comprehensive insights or create a case study for your organization, you must understand how to join these tables and extract meaningful, relevant data.</p>
<h1 id="heading-3-cte-common-table-expressions">3. CTE (Common Table Expressions)</h1>
<p>You will need <strong>CTE</strong> <strong>(Common Table Expressions)</strong> to <strong>simplify complicated queries</strong> such as nested/subqueries, multiple joins, or aggregations.</p>
<p>CTEs are used when you don’t want to complicate things during data retrieval. This will help you break down complex queries into smaller queries that are more readable and manageable and your queries will look more structured.</p>
<h3 id="heading-recursive-cte">Recursive CTE</h3>
<p>Another form of CTE, recursive CTE is useful when you need to explore or traverse relationships between data, particularly when dealing with <strong>hierarchical structures</strong> or <strong>recursive relationships</strong>.</p>
<p>For instance, if a company has data about their employees and wants to know which manager each employee reports to, you can use a recursive CTE to find the relationships between managers and their subordinates.</p>
<p>Another example could involve sales data where different products belong to multiple categories in a hierarchical structure. You can use recursive CTEs to explore how these product categories are related, for example, by traversing from top-level categories down to subcategories.</p>
<h1 id="heading-4-window-functions">4. Window Functions</h1>
<p><strong>Window functions</strong> play a crucial role in SQL. They allow you to perform a wide range of tasks, from data partitioning to time-series analysis, without altering the original structure of the data.</p>
<p>With window functions, you can carry out <strong>complex calculations</strong>, <strong>comparative analysis</strong>, and <strong>analyze data across rows</strong>, helping to derive meaningful insights while preserving row-level details.</p>
<h1 id="heading-5-conditionals">5. Conditionals</h1>
<p><strong>Conditional expressions</strong> are useful they enable <strong>dynamic and flexible querying</strong>, <strong>data transformation</strong>, and <strong>feature engineering</strong>.</p>
<p>These expressions allow you to perform calculations, filter data, or modify values based on specific conditions, which is vital for data analysis, reporting, and preparation of data for machine learning models.</p>
<p>Conditional expressions (like <code>CASE</code> or <code>IF()</code>) allow you to clean, standardize, and transform data based on certain criteria. This is essential when dealing with inconsistent or incomplete data.</p>
<h1 id="heading-6-aggregate-functions">6. Aggregate Functions</h1>
<p><strong>Aggregate functions</strong> are essential for performing <strong>mathematical computations</strong> and <strong>summarizing data</strong> across different categories or fields. They allow you to compute metrics like <strong>sums</strong>, <strong>averages</strong>, <strong>counts</strong>, and more, based on specific groups within the data.</p>
<h1 id="heading-7-plsql">7. PL/SQL</h1>
<p>While <strong>PL/SQL</strong> is less commonly used in everyday data science tasks, it's important to know how to create <strong>functions</strong>, <strong>stored procedures</strong>, <strong>triggers</strong>, and <strong>views</strong> in SQL.</p>
<p><strong>PL/SQL (Procedural Language/SQL)</strong> extends SQL with procedural programming features like <strong>loops</strong>, <strong>conditions</strong>, and <strong>exception handling</strong>, allowing for more complex operations similar to any other programming language.</p>
<p>It is particularly useful for <strong>complex data processing</strong>, <strong>automating data tasks</strong>, <strong>reusing code</strong>, and <strong>optimizing query performance</strong>, ultimately saving time and resources.</p>
<hr />
<p><strong>That’s all for now.</strong></p>
<p><strong>Keep Coding✌✌.</strong></p>
]]></content:encoded></item><item><title><![CDATA[GIL Become Optional in Python 3.13]]></title><description><![CDATA[GIL or Global Interpreter Lock can be disabled in Python version 3.13. This is currently experimental.
What is GIL? It is a mechanism used by the CPython interpreter to ensure that only one thread executes the Python bytecode at a time.
An Experiment...]]></description><link>https://teamgeek.geekpython.in/gil-become-optional-in-python-313</link><guid isPermaLink="true">https://teamgeek.geekpython.in/gil-become-optional-in-python-313</guid><category><![CDATA[Python 3]]></category><category><![CDATA[GIL]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Fri, 16 Aug 2024 09:23:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723399181102/b47d1a0f-63bf-43f7-9168-0bb58de89d6f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>GIL</strong> or <strong>Global Interpreter Lock</strong> can be disabled in Python version 3.13. This is currently experimental.</p>
<p>What is GIL? It is a mechanism used by the CPython interpreter to ensure that only one thread executes the Python bytecode at a time.</p>
<h2 id="heading-an-experimental-feature">An Experimental Feature</h2>
<p>Python 3.13 brings major new features compared to Python 3.12 and one of them is free-threaded mode, which disables the Global Interpreter Lock, allowing threads to run more concurrently.</p>
<p>This is an experimental feature and if you want to try it, you can download the beta version of Python 3.13 from <a target="_blank" href="https://www.python.org/downloads/release/python-3130b3/">here</a>.</p>
<p>At the time of installation, check the option "free threaded binaries(experimental)" to get the feature in Python.</p>
<h2 id="heading-making-gil-optional-in-python-313">Making GIL Optional in Python 3.13</h2>
<p>The GIL will be disabled when you configure the Python with the <code>--disable-gil</code> option which is nothing but a build configuration (free threading build) at the time of installation.</p>
<p>This will allow optionally enabling and disabling GIL using the environment variable <code>PYTHON_GIL</code> which can be set to <code>1</code> and <code>0</code> respectively.</p>
<p>It will also provide a command-line option <code>-X gil</code> which can also be set to <code>0</code> (disable) and <code>1</code> (enable).</p>
<pre><code class="lang-python"><span class="hljs-comment"># v3.13</span>
<span class="hljs-comment"># GIL disabled</span>
python3 -X gil=<span class="hljs-number">0</span> sample.py

<span class="hljs-comment"># GIL enabled</span>
python3 -X gil=<span class="hljs-number">1</span> sample.py
</code></pre>
<p>We can also check if the current interpreter is configured with the free threading build (<code>--disable-gil</code>) by using the following code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sysconfig
print(sysconfig.get_config_var(<span class="hljs-string">"Py_GIL_DISABLED"</span>))
</code></pre>
<p>If we run this, we'll get either <code>0</code> which means GIL is enabled, or <code>1</code> which means GIL is disabled.</p>
<p>With this, we'll also get a function that can be used to check if GIL is disabled in the running process.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
sys._is_gil_enabled()  <span class="hljs-comment"># returns a boolean value</span>
</code></pre>
<h2 id="heading-gil-vs-no-gil">GIL Vs No GIL</h2>
<p>Let's see how the performance of multi-threaded programs will be affected when GIL is enabled and disabled.</p>
<p>We have a simple Python program (<code>gil.py</code>) that computes the factorial of numbers and compares the execution time taken by single-threaded, multi-thread, and multi-process tasks. We'll run this Python program first <strong>with GIL</strong> and then <strong>without GIL</strong>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> sysconfig
<span class="hljs-keyword">import</span> math
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> threading
<span class="hljs-keyword">import</span> multiprocessing

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">compute_factorial</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">return</span> math.factorial(n)

<span class="hljs-comment"># Single-threaded</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">single_threaded_compute</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> n:
        compute_factorial(num)
    print(<span class="hljs-string">"Single-threaded: Factorial Computed."</span>)

<span class="hljs-comment"># Multi-threaded</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multi_threaded_compute</span>(<span class="hljs-params">n</span>):</span>
    threads = []
    <span class="hljs-comment"># Create 5 threads</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> n:
        thread = threading.Thread(target=compute_factorial, args=(num,))
        threads.append(thread)
        thread.start()

    <span class="hljs-comment"># Wait for all threads to complete</span>
    <span class="hljs-keyword">for</span> thread <span class="hljs-keyword">in</span> threads:
        thread.join()

    print(<span class="hljs-string">"Multi-threaded: Factorial Computed."</span>)

<span class="hljs-comment"># Multi-process</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multi_processing_compute</span>(<span class="hljs-params">n</span>):</span>
    processes = []
    <span class="hljs-comment"># Create a process for each number in the list</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> n:
        process = multiprocessing.Process(target=compute_factorial, args=(num,))
        processes.append(process)
        process.start()

    <span class="hljs-comment"># Wait for all processes to complete</span>
    <span class="hljs-keyword">for</span> process <span class="hljs-keyword">in</span> processes:
        process.join()

    print(<span class="hljs-string">"Multi-process: Factorial Computed."</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-comment"># Checking Version</span>
    print(<span class="hljs-string">f"Python version: <span class="hljs-subst">{sys.version}</span>"</span>)

    <span class="hljs-comment"># GIL Status</span>
    status = sysconfig.get_config_var(<span class="hljs-string">"Py_GIL_DISABLED"</span>)
    <span class="hljs-keyword">if</span> status <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:
        print(<span class="hljs-string">"GIL cannot be disabled"</span>)
    <span class="hljs-keyword">if</span> status == <span class="hljs-number">0</span>:
        print(<span class="hljs-string">"GIL is active"</span>)
    <span class="hljs-keyword">if</span> status == <span class="hljs-number">1</span>:
        print(<span class="hljs-string">"GIL is disabled"</span>)

    numlist = [<span class="hljs-number">100000</span>, <span class="hljs-number">200000</span>, <span class="hljs-number">300000</span>, <span class="hljs-number">400000</span>, <span class="hljs-number">500000</span>]

    <span class="hljs-comment"># Single-threaded Execution</span>
    start = time.time()
    single_threaded_compute(numlist)
    end = time.time() - start
    print(<span class="hljs-string">f"Single-threaded time taken: <span class="hljs-subst">{end:<span class="hljs-number">.2</span>f}</span> seconds"</span>)

    <span class="hljs-comment"># Multi-threaded Execution</span>
    start = time.time()
    multi_threaded_compute(numlist)
    end = time.time() - start
    print(<span class="hljs-string">f"Multi-threaded time taken : <span class="hljs-subst">{end:<span class="hljs-number">.2</span>f}</span> seconds"</span>)

    <span class="hljs-comment"># Multi-process Execution</span>
    start = time.time()
    multi_processing_compute(numlist)
    end = time.time() - start
    print(<span class="hljs-string">f"Multi-process time taken  : <span class="hljs-subst">{end:<span class="hljs-number">.2</span>f}</span> seconds"</span>)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<h3 id="heading-running-gilpy-with-gil">Running <code>gil.py</code> with GIL</h3>
<pre><code class="lang-bash">python gil.py
Python version: 3.12.2 (tags/v3.12.2:6abddd9, Feb  6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)]
GIL cannot be disabled
Single-threaded: Factorial Computed.
Single-threaded time taken: 9.04 seconds
Multi-threaded: Factorial Computed.
Multi-threaded time taken : 8.21 seconds
Multi-process: Factorial Computed.
Multi-process time taken  : 5.64 seconds
</code></pre>
<p>We have Python v3.12 in which there is no option to check the GIL status, so we got "GIL cannot be disabled".</p>
<p>The difference is not that much between the single-threaded and multi-threaded but we can see a pretty decent difference in the case of multi-process task.</p>
<h3 id="heading-running-gilpy-without-gil">Running <code>gil.py</code> without GIL</h3>
<pre><code class="lang-bash">D:/SACHIN/Python13/python3.13t gil.py
Python version: 3.13.0b3 experimental free-threading build (tags/v3.13.0b3:7b41395, Jun 27 2024, 16:17:17) [MSC v.1940 64 bit (AMD64)]
GIL is disabled
Single-threaded: Factorial Computed.
Single-threaded time taken: 9.28 seconds
Multi-threaded: Factorial Computed.
Multi-threaded time taken : 4.86 seconds
Multi-process: Factorial Computed.
Multi-process time taken  : 6.14 seconds
</code></pre>
<p>This time we have a third beta version of Python 3.13 configured with free threading build and as we can see the GIL is disabled.</p>
<p>But the most important part is we can see a massive difference in the performance of multi-threaded task and on the other side, some degradation can be seen in the performance of multi-process and single-threaded task.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/threading-module-to-create-threads-in-python">Create multi-threaded Python programs using a threading module</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/template-inheritance-in-flask">Template inheritance in Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/exec-and-eval">Difference between exec and eval in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/tempfile-in-python">Create temporary files and directories using tempfile module in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/render-images-from-flask">Upload and display images on the frontend using Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Find and Delete Mismatched Columns From DataFrames Using pandas]]></title><description><![CDATA[Data is the most valuable asset in machine learning, it solely holds the potential to make a machine learning model robust. Data plays an important role while training a model, the model trained can be underfitted or overfitted and it totally depends...]]></description><link>https://teamgeek.geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas</link><guid isPermaLink="true">https://teamgeek.geekpython.in/find-and-delete-mismatched-columns-from-dataframes-using-pandas</guid><category><![CDATA[Python]]></category><category><![CDATA[pandas]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Wed, 07 Aug 2024 18:30:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699031115994/0b2f499c-09ca-4a8c-9b0d-30a28fdd4ae5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Data is the most valuable asset in machine learning, it solely holds the potential to make a machine learning model robust. Data plays an important role while training a model, the model trained can be underfitted or overfitted and it totally depends on the data.</p>
<p>The data you've gathered should be of high quality, so structure, construct, and clean it in such a way that it has the potential to produce a robust model.</p>
<p>In this article, you'll learn how to use pandas to find and remove columns from one dataset that don't match those in another.</p>
<h2 id="heading-objective">Objective</h2>
<p>When you have multiple datasets and want to merge them to augment the data points, some columns of the datasets do not match. You must find and remove them so that they do not have an adverse effect on the model while training.</p>
<h2 id="heading-what-youll-do">What You'll Do</h2>
<p>There are a few datasets that contain used car information such as price, name, distance driven, fuel type, and more. You will search the dataset for unmatched columns and then remove them.</p>
<p>The datasets used in this article are downloaded from Kaggle.</p>
<h2 id="heading-dataset-overview">Dataset Overview</h2>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Reading Car Dataset</span>
df = pd.read_csv(<span class="hljs-string">"car.csv"</span>)
print(<span class="hljs-string">f"Shape of the Datset: <span class="hljs-subst">{df.shape}</span>"</span>)

----------
Shape of the Dataset: (<span class="hljs-number">4340</span>, <span class="hljs-number">8</span>)
</code></pre>
<p>The <code>car.csv</code> dataset has 4380 rows and <strong>8 columns</strong>, and you will now find the columns that do not match the columns of the <code>car.csv</code> dataset and remove them.</p>
<p>The following are the names of the dataset's columns:</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Column Names:"</span>)
<span class="hljs-keyword">for</span> column <span class="hljs-keyword">in</span> df.columns:
    print(column.capitalize())

----------
Column Names:
Name
Year
Selling_price
Km_driven
Fuel
Seller_type
Transmission
Owner
</code></pre>
<p>You now know which columns to keep in the second dataset and which to remove.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Reading Car Dataset</span>
df = pd.read_csv(<span class="hljs-string">"used_car.csv"</span>)
print(<span class="hljs-string">f"Shape of the Datset: <span class="hljs-subst">{df.shape}</span>"</span>)

----------
Shape of the Dataset: (<span class="hljs-number">7906</span>, <span class="hljs-number">18</span>)
</code></pre>
<p>As you can see the <code>used_car.csv</code> dataset has 7906 rows and <strong>18 columns</strong>. This dataset contains more columns, but you must keep the columns consistent with the <code>car.csv</code> dataset and remove the remaining ten columns from the <code>used_car.csv</code> dataset.</p>
<h2 id="heading-finding-mismatched-columns">Finding Mismatched Columns</h2>
<p>In this section, you will identify the columns in the <code>used_car.csv</code> dataset that are not present in the <code>car.csv</code> dataset.</p>
<pre><code class="lang-python">columns_to_delete = df2.columns.difference(df.columns)
</code></pre>
<p>The above code will find the columns that are not present in the <code>car.csv</code> dataset from the <code>used_car.csv</code> dataset using the <code>difference()</code> method on the dataset's <code>columns</code> attribute. The result will be stored inside the <code>columns_to_delete</code> variable.</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Columns not Present in First Dataset:"</span>)
<span class="hljs-keyword">for</span> counter, col <span class="hljs-keyword">in</span> enumerate(columns_to_delete, start=<span class="hljs-number">1</span>):
    print(<span class="hljs-string">f"<span class="hljs-subst">{counter}</span>- <span class="hljs-subst">{col}</span>"</span>)
</code></pre>
<p>The above code will list all the columns that are not present in the <code>car.csv</code> dataset. Run the above code and you'll get the following output.</p>
<pre><code class="lang-bash">Columns not Present <span class="hljs-keyword">in</span> First Dataset:
1- City
2- Region
3- Sales_ID
4- State or Province
5- engine
6- max_power
7- mileage
8- seats
9- sold
10- torque
</code></pre>
<p>There are a total of <code>10</code> columns that are not present in the <code>car.csv</code> dataset. The next step is to delete or remove them from the <code>used_car.csv</code> dataset.</p>
<h2 id="heading-deleting-mismatched-columns">Deleting Mismatched Columns</h2>
<p>In this section, you will delete the above-identified columns from the <code>used_car.csv</code> dataset and <code>pandas</code> provide a much simpler way to do this.</p>
<pre><code class="lang-python">new_df2 = df2.drop(columns_to_delete, axis=<span class="hljs-number">1</span>)
</code></pre>
<p>The above code will delete all those 10 columns from the <code>used_car.csv</code> dataset using the <code>drop()</code> function on <code>df2</code> along the columns axis (<code>axis=1</code>). The new dataset is stored inside the <code>new_df2</code> variable.</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Columns Present in the Second Dataset:"</span>)
<span class="hljs-keyword">for</span> column <span class="hljs-keyword">in</span> new_df2.columns:
    print(column.capitalize())
</code></pre>
<p>The above code will print the column names that remain in the <code>used_car.csv</code> dataset.</p>
<pre><code class="lang-bash">Columns Present <span class="hljs-keyword">in</span> the Second Dataset:
Name
Year
Selling_price
Km_driven
Fuel
Seller_type
Transmission
Owner
</code></pre>
<p>Now both datasets <code>car.csv</code> and <code>used_car.csv</code> contain the same columns. You can now <a target="_blank" href="https://geekpython.in/multiple-datasets-integration-using-pandas">merge</a> both datasets along the row axis to augment the data.</p>
<p>Save <code>new_df2</code> as the new dataset in CSV format using the pandas to use it for further purposes.</p>
<pre><code class="lang-python">new_df2.to_csv(<span class="hljs-string">'new_car_data.csv'</span>, index=<span class="hljs-literal">False</span>)
</code></pre>
<p>The above code will save <code>new_df2</code> as <code>new_car_data.csv</code> in the current directory.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Data cleaning is a critical step in the data preprocessing pipeline, ensuring that your data is of high quality and suitable for building accurate and robust machine learning models.</p>
<p>Any irregularity in data can make a huge difference in the model's training. So you need to make a consistent dataset.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/multiple-datasets-integration-using-pandas">Merge, combine, and concatenate multiple datasets using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/find-and-delete-duplicate-rows-from-dataset">Find and delete duplicate rows from the dataset using pandas</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/threading-module-to-create-threads-in-python">Create multi-threaded Python programs using a threading module</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/tempfile-in-python">Create temporary files and directories using tempfile module in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/render-images-from-flask">Upload and display images on the frontend using Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/impact-of-learning-rates-on-ml-and-dl-models">How does the learning rate affect the ML and DL models</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Template Inheritance in Flask]]></title><description><![CDATA[What is template inheritance? A web application has a minimum of four to five pages. These pages contain common components like header, footer, background, etc. So, these components collectively put into a template for reusability.
Other pages of the...]]></description><link>https://teamgeek.geekpython.in/template-inheritance-in-flask</link><guid isPermaLink="true">https://teamgeek.geekpython.in/template-inheritance-in-flask</guid><category><![CDATA[Flask Framework]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Sun, 04 Aug 2024 18:30:31 GMT</pubDate><content:encoded><![CDATA[<p>What is template inheritance? A web application has a minimum of four to five pages. These pages contain common components like header, footer, background, etc. So, these components collectively put into a template for reusability.</p>
<p>Other pages of the application inherit these templates, hence the process is called <strong>template inheritance</strong>. Let's see how we can do the same in <strong>Flask</strong>.</p>
<p>Every webpage has a header specifically a navigation bar and a footer displaying the business's objective and important hyperlinks to different services.</p>
<p>Let's say we have a directory structure that looks like the following:</p>
<pre><code class="lang-python">flask_project/
|- app.py
|- templates
    |- base_layout.html
    |- about.html
    |- product.html
|- static
</code></pre>
<p>We need to create a Flask app to serve our templates. Add the following code into the <code>app.py</code> file.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template

app = Flask(__name__)

<span class="hljs-meta">@app.route("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"base_layout.html"</span>)

<span class="hljs-meta">@app.route("/about")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">about</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"about.html"</span>)

<span class="hljs-meta">@app.route("/products")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">products</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"product.html"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>We have three templates that will be rendered on their respective URLs that's why we created three routes (<code>/</code>, <code>/about</code>, and <code>/products</code>) in our app.</p>
<p>Here's a simple navbar and footer using Bootstrap.</p>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- base_layout.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Template Inheritance<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Bootstrap CSS --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-comment">&lt;!-- Navbar --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar navbar-expand-lg bg-info"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Navbar<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"collapse navbar-collapse"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"navbarNavAltMarkup"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-nav"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link active"</span> <span class="hljs-attr">aria-current</span>=<span class="hljs-string">"page"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Main Content of Page --&gt;</span>
{% block content %}
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> This is Homepage <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
{% endblock %}

<span class="hljs-comment">&lt;!-- Footer --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-dark text-white"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container py-4"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-0"</span>&gt;</span>© 2024 Your Company. All rights reserved.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Now run the app and go to this URL <code>http://127.0.0.1:5000</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722517100555/85fd7bfa-bff7-4f14-863c-5b72d7726743.png" alt="base_layout webpage" class="image--center mx-auto" /></p>
<p>Our webpage now has a simple layout. The next goal is to avoid explicitly including the identical components (navbar and footer) on each page (<code>about.html</code> and <code>product.html</code>).</p>
<p>As a result, we will use <code>base_layout.html</code> as our base template to include the navbar and footer on subsequent web pages.</p>
<p>How'll we do that? Of course, by using <strong>template inheritance</strong>. Let's start things off.</p>
<p>Here, we'll use <strong>Jinja</strong> syntax to achieve our goal. In the <code>about.html</code> add the following code.</p>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- about.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Base template layout --&gt;</span>
{% extends 'base_layout.html' %}

<span class="hljs-comment">&lt;!-- Main Content of Page --&gt;</span>
{% block content %}
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> This is About Page <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
{% endblock %}
</code></pre>
<p>This line (<code>{% extends 'base_layout.html' %}</code>) indicates that the <code>about.html</code> template will use the <code>base_layout.html</code> template as its base. This means that <code>about.html</code> inherits the structure and layout defined in <code>base_layout.html</code>.</p>
<p>If you've noticed, we inserted the content block (<code>{% block content %}{% endblock %}</code>) in our base template, which will help us serve the dynamic content. This is what we've done after extending the base layout.</p>
<p>Now, we can insert anything within the content block using the above syntax, in this case, we've inserted a simple <code>&lt;h1&gt;</code> tag.</p>
<p>This is the result we got, <code>about.html</code> serving on <code>http://127.0.0.1:5000/about</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722519720405/4bcfd648-200f-40af-b691-e4c90792c7ec.png" alt="About page using base layout" class="image--center mx-auto" /></p>
<p>Similarly, we can do this in <code>product.html</code> as well.</p>
<pre><code class="lang-xml"><span class="hljs-comment">&lt;!-- product.html --&gt;</span>

<span class="hljs-comment">&lt;!-- Base template layout --&gt;</span>
{% extends 'base_layout.html' %}

<span class="hljs-comment">&lt;!-- Main Content of Page --&gt;</span>
{% block content %}
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> This is Product Page <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
{% endblock %}
</code></pre>
<p>This time we are serving different content. Here's the result.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722519891594/82e37761-7bf1-4268-be8b-29ab828660fe.png" alt="Product page using base layout" class="image--center mx-auto" /></p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/type-hinting-in-python">Type hints in Python - Callable objects, Return values, and more</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/positional-and-keyword-arguments-in-python">Best Practices: Positional and Keyword Arguments in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/yield-keyword-in-python">Yield Keyword in Python with Examples</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/build-websocket-server-and-client-using-python">Create a WebSocket Server and Client in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/mysql-database-in-python">Create and Interact with MySQL Database in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/understanding-the-use-of-global-keyword-in-python">Understanding the use of global keyword in Python</a>.</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Difference between exec() and eval() functions]]></title><description><![CDATA[Both functions have a common objective: to execute Python code from the string input or code object. Even though they both have the same objective, exec() and eval() are not the same.
Return Values
The exec() function doesn't return any value whereas...]]></description><link>https://teamgeek.geekpython.in/difference-between-exec-and-eval-functions</link><guid isPermaLink="true">https://teamgeek.geekpython.in/difference-between-exec-and-eval-functions</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Sat, 03 Aug 2024 08:20:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722673149541/598d5662-b29d-4771-b427-fa701a0b77d7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Both functions have a common objective: <strong>to execute Python code from the string input or code object</strong>. Even though they both have the same objective, <code>exec()</code> and <code>eval()</code> are not the same.</p>
<h3 id="heading-return-values">Return Values</h3>
<p>The <code>exec()</code> function doesn't return any value whereas the <code>eval()</code> function returns a value computed from the expression.</p>
<pre><code class="lang-python">expression = <span class="hljs-string">"3 + 5"</span>

result_eval = eval(expression)
print(result_eval)

result_exec = exec(expression)
print(result_exec)
</code></pre>
<p>When we run this code, we'll get <code>8</code> and <code>None</code>. This means that <code>eval(expression)</code> evaluated the result and stored it inside <code>result_eval</code> whereas <code>exec(expression)</code> returned nothing, so the value <code>None</code> gets stored into <code>result_exec</code>.</p>
<pre><code class="lang-bash">8
None
</code></pre>
<h3 id="heading-execution">Execution</h3>
<p>The <code>exec()</code> function is capable of executing multi-line and multi-statment code, it doesn't matter whether the code is simple, complex, has loops and conditions, classes, and functions.</p>
<p>On the other hand, the <code>eval()</code> function is restricted to executing the single-line code which might be a simple or complex expression.</p>
<pre><code class="lang-python">expression = <span class="hljs-string">"""
for x in range(5):
    print(x, end=" ")
"""</span>

exec(expression)
eval(expression)
</code></pre>
<p>Look at this code, we have a multi-line code that prints numbers up to the given range. The <code>exec(expression)</code> will execute it and display the result but the <code>eval(expression)</code> will display the error.</p>
<pre><code class="lang-bash">0 1 2 3 4
SyntaxError: invalid syntax
</code></pre>
<p>However, if we convert the same expression into a single line as the following, the <code>eval(expression)</code> will not throw any error.</p>
<pre><code class="lang-bash">expression = <span class="hljs-string">"[print(x, end=' ') for x in range(5)]"</span>
<span class="hljs-built_in">eval</span>(expression)

--------------------
0 1 2 3 4
</code></pre>
<h3 id="heading-summary">Summary</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>eval()</td><td>exec()</td></tr>
</thead>
<tbody>
<tr>
<td>Returns a value</td><td>Doesn't return any value</td></tr>
<tr>
<td>Executes a single expression, it might be simple or complex</td><td>Capable of executing multi-statement and multi-line expressions containing loops, conditions, functions, and classes</td></tr>
<tr>
<td>Use <code>eval()</code> when you need to evaluate a single expression and use its result.</td><td>Use <code>exec()</code> when you need to execute complex code blocks or multiple statements.</td></tr>
</tbody>
</table>
</div><hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/exec-function-in-python">Execute complex code blocks from string input using exec() function</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/template-inheritance-in-flask">Template inheritance in Flask</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/type-hinting-in-python">Type hints in Python - Callable objects, Return values, and more</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/positional-and-keyword-arguments-in-python">Best Practices: Positional and Keyword Arguments in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/yield-keyword-in-python">Yield Keyword in Python with Examples</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/build-websocket-server-and-client-using-python">Create a WebSocket Server and Client in Python</a>.</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Python Logging: Basic and Advanced Configuration]]></title><description><![CDATA[Logging debug or error messages is crucial for any application as it helps developers supervise and troubleshoot the application efficiently.
Python provides a module named logging to log messages. These messages can be written to various destination...]]></description><link>https://teamgeek.geekpython.in/python-logging-basic-and-advanced-configuration</link><guid isPermaLink="true">https://teamgeek.geekpython.in/python-logging-basic-and-advanced-configuration</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Thu, 13 Jun 2024 18:30:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1718292661470/747757dd-ce98-4423-9aa5-918da5834e73.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Logging debug or error messages is crucial for any application as it helps developers supervise and troubleshoot the application efficiently.</p>
<p>Python provides a module named <code>logging</code> to log messages. These messages can be written to various destinations, including files, for better monitoring and debugging of programs.</p>
<p>In this article, you'll learn:</p>
<ul>
<li><p><strong>Logging a simple message using the logging module</strong></p>
</li>
<li><p><strong>Severity level of the messages</strong></p>
</li>
<li><p><strong>Configuring the</strong><code>logging</code><strong>module to log</strong><code>INFO</code><strong>and</strong><code>DEBUG</code><strong>level messages and logging events to a file</strong></p>
</li>
<li><p><strong>Logging the variable data</strong></p>
</li>
<li><p><strong>Formatting the log messages using LogRecord attributes</strong></p>
</li>
<li><p><strong>Advanced Configurations: Loggers, Handlers and Formatters</strong></p>
</li>
<li><p><strong>Practical example</strong></p>
</li>
</ul>
<h2 id="heading-logging-messages">Logging Messages</h2>
<p>Here's an example of logging a simple message on the console using the <code>logging</code> module in Python.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Imported logging module</span>
<span class="hljs-keyword">import</span> logging

num = <span class="hljs-number">0</span>
<span class="hljs-comment"># Logs a warning message</span>
logging.warning(<span class="hljs-string">"Entering Infinite Loop"</span>)
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    <span class="hljs-keyword">if</span> num % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>:
        print(num)
    num += <span class="hljs-number">1</span>
</code></pre>
<p>The code above runs endlessly, thus when it runs, a warning message will be logged to alert the user.</p>
<p>Here, <code>logging.warning()</code> has been used to log the warning message to the console. The <code>warning</code> here is the severity level of the message.</p>
<pre><code class="lang-bash">WARNING:root:Entering Infinite Loop
0
2
4
.
.
.
</code></pre>
<p>As you can see, the output begins by logging the warning message <strong>"Entering Infinite Loop"</strong> in the pattern <code>WARNING:root:&lt;message&gt;</code>, indicating the severity level and name assigned by the logger respectively.</p>
<p>Similar to this, the <code>logging</code> module offers several levels to show the events' severity.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Imported logging module</span>
<span class="hljs-keyword">import</span> logging

logging.info(<span class="hljs-string">"Used to log info message"</span>)
logging.debug(<span class="hljs-string">"Used to log debug message"</span>)
logging.warning(<span class="hljs-string">"Used to log warning message"</span>)
logging.error(<span class="hljs-string">"Used to log error message"</span>)
logging.critical(<span class="hljs-string">"Used to log critical message"</span>)
</code></pre>
<p>There are 5 different levels to log messages of different severity levels.</p>
<ul>
<li><p><strong>INFO</strong></p>
</li>
<li><p><strong>DEBUG</strong></p>
</li>
<li><p><strong>WARNING</strong></p>
</li>
<li><p><strong>ERROR</strong></p>
</li>
<li><p><strong>CRITICAL</strong></p>
</li>
</ul>
<pre><code class="lang-bash">WARNING:root:Used to <span class="hljs-built_in">log</span> warning message
ERROR:root:Used to <span class="hljs-built_in">log</span> error message
CRITICAL:root:Used to <span class="hljs-built_in">log</span> critical message
</code></pre>
<p>You can observe that the output is missing the first two messages. <strong>Why is it so?</strong> The messages with a severity level of <code>WARNING</code> and above are logged by the <code>logging</code> module.</p>
<p>You can log <code>INFO</code> and <code>DEBUG</code> messages by applying some configurations.</p>
<h2 id="heading-configuring-logging-module">Configuring Logging Module</h2>
<p>The <code>logging</code> module can be configured to unleash more power to let you do more stuff when logging events.</p>
<h3 id="heading-basic-configuration">Basic Configuration</h3>
<p>The <code>logging</code> module includes a function called <code>basicConfig()</code> that helps in configuring the logging system. Here's an example of configuring <code>logging</code> module to log <code>INFO</code> level message.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Configuring logging</span>
logging.basicConfig(level=logging.INFO)
logging.info(<span class="hljs-string">"This info will be printed"</span>)
</code></pre>
<p>The <code>logging</code> module is configured in the code above to log a <code>INFO</code> message by passing the keyword argument <code>level</code> to the <code>basicConfig()</code> function and setting it to <code>logging.INFO</code>.</p>
<p>When you run the above code, the severity level <code>INFO</code> message will now be printed.</p>
<pre><code class="lang-bash">INFO:root:This info will be printed
</code></pre>
<p>Similarly, you can log <code>DEBUG</code> messages by setting the <code>level</code> argument to the value <code>logging.DEBUG</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Configuring logging to log DEBUG msg</span>
logging.basicConfig(level=logging.DEBUG)
logging.debug(<span class="hljs-string">"This is a DEBUG message"</span>)

--------------------
DEBUG:root:This <span class="hljs-keyword">is</span> a DEBUG message
</code></pre>
<h3 id="heading-logging-event-to-a-file">Logging Event to a File</h3>
<p>The <code>basicConfig()</code> function accepts a keyword argument called <code>filename</code> to specify the file in which the event will be logged.</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Logging to a file</span>
logging.basicConfig(filename=<span class="hljs-string">'debug.log'</span>, level=logging.DEBUG)
logging.debug(<span class="hljs-string">"This is a DEBUG message"</span>)
</code></pre>
<p>The message will be logged into the <code>debug.log</code> file and it will be the same as the previous output but in the file instead of the console.</p>
<p>By default, the mode of the file is set to append (<code>a</code>) mode and you can change this by specifying the <code>filemode</code> parameter. Additionally, you can use the <code>encoding</code> parameter to specify the file's encoding.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Logging to a file</span>
logging.basicConfig(filename=<span class="hljs-string">'debug_new.log'</span>,
                    filemode=<span class="hljs-string">'w'</span>,
                    encoding=<span class="hljs-string">'utf-8'</span>,
                    level=logging.DEBUG)
logging.debug(<span class="hljs-string">"Debugging starts from here."</span>)
</code></pre>
<p>In this example, the file is set to write (<code>filemode='w'</code>) mode and encoding is set to <code>'utf-8'</code>. This time the message will be logged into the <code>debug_new.log</code> file.</p>
<h2 id="heading-how-to-log-variable-data">How to Log Variable Data?</h2>
<p>Logging variable data is similar to formatting a string using the <code>%</code> operator. This helps when you want to include dynamic data in logged messages.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Logging variable data</span>
logging.error(<span class="hljs-string">"%s: Not found - Status: %s"</span>, <span class="hljs-number">404</span>, <span class="hljs-string">"Fail"</span>)
</code></pre>
<p>In this code, two placeholders (<code>%s</code>) are present in the string that will help Python interpolate the string with the specified values i.e., <code>404</code> and <code>'Fail'</code>, and they will be placed in the same position as they appear.</p>
<p>When you run the code, you'll get the following output.</p>
<pre><code class="lang-python">ERROR:root:<span class="hljs-number">404</span>: Not found - Status: Fail
</code></pre>
<h2 id="heading-formatting-the-logged-messages">Formatting the Logged Messages</h2>
<p>You now know how to log variable data; in this section, you'll utilize it to format the logged messages.</p>
<p>You can choose the format of your logged message to be displayed in the console or a file.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

logging.basicConfig(format=<span class="hljs-string">'%(levelname)s - %(message)s'</span>)
logging.warning(<span class="hljs-string">"Things are getting worse."</span>)

--------------------
WARNING - Things are getting worse.
</code></pre>
<p>As you can see, the message is logged with the formatting that the <code>format</code> argument set. The severity (<code>levelname</code>) is shown first, then the event's description (<code>message</code>).</p>
<p>You may be wondering now where the <code>message</code> and <code>levelname</code> came from. Well, these are the attributes specified by the <a target="_blank" href="https://docs.python.org/3/library/logging.html#logrecord-attributes">LogRecord</a>. Similarly, LogRecord has more attributes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

logging.basicConfig(
    format=<span class="hljs-string">'%(levelname)s: %(message)s - %(asctime)s'</span>, 
    level=logging.DEBUG
)
logging.debug(<span class="hljs-string">"Debugging started at"</span>)
</code></pre>
<p>Now, this time a new attribute <code>asctime</code> is added to the message that logs the date and time of the event. The output looks like the following.</p>
<pre><code class="lang-bash">DEBUG: Debugging started at - 2024-06-12 16:37:55,996
</code></pre>
<p>You can take more control of formatting the date and time of the event by passing the <code>datefmt</code> argument in the <code>basicConfig()</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

logging.basicConfig(
    format=<span class="hljs-string">'%(levelname)s: %(message)s - %(asctime)s'</span>,
    datefmt=<span class="hljs-string">'%d/%m/%Y %I:%M:%S %p'</span>, 
    level=logging.DEBUG
)
logging.debug(<span class="hljs-string">"Debugging started at"</span>)

--------------------
DEBUG: Debugging started at - <span class="hljs-number">12</span>/<span class="hljs-number">06</span>/<span class="hljs-number">2024</span> <span class="hljs-number">05</span>:<span class="hljs-number">55</span>:<span class="hljs-number">38</span> PM
</code></pre>
<p>The date and time looks more readable now due to the string (<code>'%d/%m/%Y %I:%M:%S %p'</code>) set by the <code>datefmt</code> argument. You can experiment with the characters within the string just like you would do in the <a target="_blank" href="https://docs.python.org/3/library/time.html#time.strftime"><code>time.strftime()</code></a><strong>.</strong> Here's an example.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

logging.basicConfig(
    format=<span class="hljs-string">'%(levelname)s: %(message)s - %(asctime)s'</span>,
    datefmt=<span class="hljs-string">'%d %b %Y %a %I:%M:%S %p'</span>, 
    level=logging.DEBUG
)
logging.debug(<span class="hljs-string">"Debugging started at"</span>)

--------------------
DEBUG: Debugging started at - <span class="hljs-number">12</span> Jun <span class="hljs-number">2024</span> Wed <span class="hljs-number">06</span>:<span class="hljs-number">08</span>:<span class="hljs-number">20</span> PM
</code></pre>
<p>You can add some more attributes such as file name, module name, process ID, name of the logger, and much more.</p>
<p>So far you've learned to log messages at the basic level. In the next section, you'll learn to log messages at an advanced level such as configuring your logger, sending the log messages over multiple destinations, and much more.</p>
<h2 id="heading-logging-advanced-configurations">Logging - Advanced Configurations</h2>
<p>In this section, you'll use classes and functions to log messages. The commonly used classes in the <code>logging</code> module are as follows:</p>
<ul>
<li><p><strong>Logger</strong> - Used to create logger objects so that logging can be performed by calling different methods on its objects.</p>
</li>
<li><p><strong>Handler</strong> - Used to send log messages to appropriate destinations such as into the file, email, HTTP server, etc.</p>
</li>
<li><p><strong>Formatter</strong> - Used to set the format of the log records in the final output.</p>
</li>
</ul>
<h3 id="heading-creating-logger-object">Creating Logger Object</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Create a logger</span>
logger = logging.getLogger(<span class="hljs-string">"custom_logger"</span>)
logger.warning(<span class="hljs-string">"Warning... Warning..."</span>)
</code></pre>
<p>In this example, a custom logger named <code>custom_logger</code> is created using <code>logging.getLogger()</code>. When you run this code, you'll get the following output.</p>
<pre><code class="lang-python">Warning... Warning...
</code></pre>
<p>This is a simple message without the severity level and logger name even though the name of the logger was specified. This is because the custom logger can't be configured using <code>basicConfig()</code>. To format this output, you need to use <strong>Handlers</strong> and <strong>Formatters</strong>.</p>
<blockquote>
<p>An important note:</p>
<p>It is a good practice to name your logger based on module like the following.</p>
<p><code>logger = logging.getLogger(__name__)</code></p>
<p>This will keep track of your module/package hierarchy. It means if you are using it in same module, the logger name will be <code>__main__</code> and if you import this module into another module, then the logger name will the <code>module_name</code>, the name of the module in which it is defined.</p>
</blockquote>
<p>The logger object doesn't log messages of severity level <code>DEBUG</code> and <code>INFO</code>. To log <code>DEBUG</code> or <code>INFO</code> level messages using the custom logger, you need to create a handler.</p>
<h3 id="heading-creating-handler">Creating Handler</h3>
<p>Handler objects are responsible for logging records to the specified destinations. There are several handler types such as <a target="_blank" href="https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler"><code>StreamHandler</code></a>, <a target="_blank" href="https://docs.python.org/3/library/logging.handlers.html#logging.FileHandler"><code>FileHandler</code></a>, <a target="_blank" href="https://docs.python.org/3/library/logging.handlers.html#logging.handlers.HTTPHandler"><code>HTTPHandler</code></a>, <a target="_blank" href="https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SMTPHandler"><code>SMTPHandler</code></a> and <a target="_blank" href="https://docs.python.org/3/howto/logging.html#useful-handlers">more</a>.</p>
<p>The <code>addHandler()</code> method is used to add one or more handlers to the logger object. You need to add the individual handler to log messages based on categories to different destinations.</p>
<p>After creating a logger object in the previous section, the next step is to create the handler.</p>
<pre><code class="lang-python"><span class="hljs-comment"># adv_logging.py</span>

<span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Create a logger</span>
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)  <span class="hljs-comment"># Set the logger's level</span>

<span class="hljs-comment"># Creating Handlers</span>
<span class="hljs-comment"># Console handler</span>
cs_handler = logging.StreamHandler()
cs_handler.setLevel(logging.INFO)

<span class="hljs-comment"># File handler</span>
fl_handler = logging.FileHandler(<span class="hljs-string">"info.log"</span>)
fl_handler.setLevel(logging.ERROR)
</code></pre>
<p>In this code, some modifications have been done to the logger object such as the logger's name changed and the logger's level has been set to <code>INFO</code>.</p>
<p>Two handlers have been created <code>cs_handler</code> and <code>fl_handler</code>. The first handler (<code>cs_handler</code>) is responsible for sending messages in the console and its level is set to <code>INFO</code>. The second handler (<code>fl_handler</code>) sends the messages to the file name <code>info.log</code> which is set to <code>ERROR</code> level.</p>
<h3 id="heading-creating-formatters">Creating Formatters</h3>
<p>Formatters are responsible for applying the formatting of the developer's choice to the final output.</p>
<p>It is similar to the formatting you've learned while setting up the basic configurations of the messages using <code>basicConfig()</code>. But here, you need to use a <code>Formatter</code> class of the <code>logging</code> module.</p>
<p>Here's the extension of the previous code.</p>
<pre><code class="lang-python">...

<span class="hljs-comment"># Creating Formatters</span>
<span class="hljs-comment"># Formatter for console</span>
cs_formatter = logging.Formatter(
    <span class="hljs-string">'%(asctime)s: %(name)s - %(levelname)s: %(message)s'</span>,
    datefmt=<span class="hljs-string">'%d %b %Y %a %I:%M:%S %p'</span>
)
<span class="hljs-comment"># Setting formatter to handler</span>
cs_handler.setFormatter(cs_formatter)

<span class="hljs-comment"># Formatter for file</span>
fl_formatter = logging.Formatter(
    <span class="hljs-string">'%(asctime)s: %(name)s - %(levelname)s: %(message)s'</span>,
    datefmt=<span class="hljs-string">'%d %b %Y %a %I:%M:%S %p'</span>
)
<span class="hljs-comment"># Setting formatter to handler</span>
fl_handler.setFormatter(fl_formatter)
</code></pre>
<p>The formatters <code>cs_formatter</code> and <code>fl_formatter</code> have been created. The formatting style of both formatters is identical, and <code>setFormatter()</code> has been used to assign each formatter to its corresponding handler.</p>
<p>To log messages with applied configurations, the final step is to add these handlers (<code>cs_handler</code> and <code>fl_handler</code>) to the logger.</p>
<pre><code class="lang-python">...

<span class="hljs-comment"># Adding handler to logger</span>
logger.addHandler(cs_handler)
logger.addHandler(fl_handler)
</code></pre>
<p>Now add messages to be logged.</p>
<pre><code class="lang-python">...

logger.info(<span class="hljs-string">"Process started..."</span>)
logger.warning(<span class="hljs-string">"Warning... Warning..."</span>)
logger.error(<span class="hljs-string">"Unusual activity detected..."</span>)
logger.critical(<span class="hljs-string">"System security compromised..."</span>)
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">13 Jun 2024 Thu 03:55:24 PM: __main__ - INFO: Process started...
13 Jun 2024 Thu 03:55:24 PM: __main__ - WARNING: Warning... Warning...
13 Jun 2024 Thu 03:55:24 PM: __main__ - ERROR: Unusual activity detected...
13 Jun 2024 Thu 03:55:24 PM: __main__ - CRITICAL: System security compromised...
</code></pre>
<p>Here, the <code>logging.info()</code>, <code>logging.warning()</code>, <code>logging.error()</code>, <code>logging.critical()</code> passed the information to the handlers (<code>cs_haldler</code> and <code>fl_handler</code>).</p>
<p>Since the logger's level is set to <code>INFO</code> and <code>cs_handler</code> is a <code>StreamHandler</code> set to <code>INFO</code> level printed the messages with specified formatting of <code>INFO</code> level and above in the console.</p>
<p>The <code>fl_handler</code> is a <code>FileHandler</code> which is set to <code>ERROR</code> level will log the messages in the <code>info.log</code> file of the level <code>ERROR</code> and above.</p>
<pre><code class="lang-plaintext">13 Jun 2024 Thu 03:55:24 PM: __main__ - ERROR: Unusual activity detected...
13 Jun 2024 Thu 03:55:24 PM: __main__ - CRITICAL: System security compromised...
</code></pre>
<p>You can see that the name of the logger is logged as <code>__main__</code> which means the source file is executed directly. If you import this module to another file and then run it, the name of the logger will change.</p>
<p>Create a new Python file, in this case, <code>sample_log.py</code>. Import the source file into it, and then run the file.</p>
<pre><code class="lang-python"><span class="hljs-comment"># sample_log.py</span>
<span class="hljs-keyword">import</span> adv_logging
</code></pre>
<p>When you run this file, your output will look like the following.</p>
<pre><code class="lang-bash">13 Jun 2024 Thu 03:58:12 PM: adv_logging - INFO: Process started...
13 Jun 2024 Thu 03:58:12 PM: adv_logging - WARNING: Warning... Warning...
13 Jun 2024 Thu 03:58:12 PM: adv_logging - ERROR: Unusual activity detected...
13 Jun 2024 Thu 03:58:12 PM: adv_logging - CRITICAL: System security compromised...
</code></pre>
<p>The <code>info.log</code> file will look like the following.</p>
<pre><code class="lang-plaintext">13 Jun 2024 Thu 03:55:24 PM: __main__ - ERROR: Unusual activity detected...
13 Jun 2024 Thu 03:55:24 PM: __main__ - CRITICAL: System security compromised...
13 Jun 2024 Thu 03:58:12 PM: adv_logging - ERROR: Unusual activity detected...
13 Jun 2024 Thu 03:58:12 PM: adv_logging - CRITICAL: System security compromised...
</code></pre>
<h2 id="heading-practical-example">Practical Example</h2>
<p>You've learned to create the logger and handlers with specified formatting. Now you can create a template for logging the messages and include it in your project code to log messages dynamically.</p>
<p>Here's a practical example of creating a logger with advanced configurations and then including it in the main script to log messages in a file.</p>
<p>First, create a Python file, in this case, <code>log_temp.py</code>. This file holds a template for logging a message.</p>
<pre><code class="lang-python"><span class="hljs-comment"># log_temp.py</span>
<span class="hljs-keyword">import</span> logging

<span class="hljs-comment"># Create a logger</span>
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

<span class="hljs-comment"># File handler</span>
fl_handler = logging.FileHandler(<span class="hljs-string">"log_file.log"</span>)
fl_handler.setLevel(logging.INFO)

<span class="hljs-comment"># Formatter for file</span>
fl_formatter = logging.Formatter(
    <span class="hljs-string">'%(name)s - %(levelname)s: %(message)s'</span>
)
<span class="hljs-comment"># Setting formatter to handler</span>
fl_handler.setFormatter(fl_formatter)

<span class="hljs-comment"># Adding handler to logger</span>
logger.addHandler(fl_handler)

<span class="hljs-comment"># Function to log INFO level msg</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">info_msg</span>(<span class="hljs-params">msg</span>):</span>
    logger.info(msg)
<span class="hljs-comment"># Function to log WARNING level msg</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">warning_msg</span>(<span class="hljs-params">msg</span>):</span>
    logger.warning(msg)
<span class="hljs-comment"># Function to log ERROR level msg</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">error_msg</span>(<span class="hljs-params">msg</span>):</span>
    logger.error(msg)
</code></pre>
<p>This code is pretty much the same as you saw in the previous sections but this time three functions are added: <code>info_msg()</code>, <code>warning_msg()</code>, and <code>error_msg()</code>.</p>
<p>These functions log <code>INFO</code>, <code>WARNING</code>, and <code>ERROR</code> level messages. The messages will be provided by the developer.</p>
<p>This template uses <code>FileHandler</code> to log messages in a file of level <code>INFO</code> and above.</p>
<p>Now, create another Python file, in this case, <code>script.py</code>, and dump the following code or write your own Python program.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Imported template</span>
<span class="hljs-keyword">import</span> log_temp

<span class="hljs-keyword">try</span>:
    num = <span class="hljs-number">0</span>
    <span class="hljs-comment"># Logs a warning message</span>
    log_temp.warning_msg(<span class="hljs-string">"Entering Infinite Loop"</span>)
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        <span class="hljs-keyword">if</span> num % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>:
            print(num)
        num += <span class="hljs-number">1</span>

<span class="hljs-keyword">except</span> KeyboardInterrupt:
    <span class="hljs-comment"># Logs an error message</span>
    log_temp.error_msg(<span class="hljs-string">"Program Interrupted"</span>)

<span class="hljs-comment"># Logs an info</span>
log_temp.info_msg(<span class="hljs-string">"Program continued"</span>)
print(<span class="hljs-string">"Exited infinite loop"</span>)
</code></pre>
<p>This code runs infinitely and when it runs, it logs a warning message and if the loop is interrupted, it logs an error message followed by the info that the program continued after exiting the loop.</p>
<p>When you run the <code>script.py</code> file, you'll get these details logged into the <code>log_file.log</code> file.</p>
<pre><code class="lang-python">log_temp - WARNING: Entering Infinite Loop
log_temp - ERROR: Program Interrupted
log_temp - INFO: Program continued
</code></pre>
<p>When the code starts executing, a warning message is logged, and then when the program gets interrupted, an error message is logged followed by the info message that provides info that the program continued after interruption.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Keeping log records of the applications can help better supervise and troubleshoot them. Python provides a standard library named logging for recording log messages for your applications.</p>
<p>You can apply basic and advanced configurations to the logging module to unleash more power. You can log messages in the console as well as to various destinations like inside a file, email, HTTP connection, etc.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/type-hinting-in-python">Type hints in Python - Callable objects, Return values, and more</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/positional-and-keyword-arguments-in-python">Best Practices: Positional and Keyword Arguments in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/yield-keyword-in-python">Yield Keyword in Python with Examples</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/build-websocket-server-and-client-using-python">Create a WebSocket Server and Client in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/mysql-database-in-python">Create and Interact with MySQL Database in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/understanding-the-use-of-global-keyword-in-python">Understanding the use of global keyword in Python</a>.</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[What is global Keyword in Python?]]></title><description><![CDATA[In Python, variables can be declared in two main scopes: global and local. Global variables are accessible from anywhere in the code, while local variables are only accessible within the function or block where they are defined.
Python has the "globa...]]></description><link>https://teamgeek.geekpython.in/what-is-global-keyword-in-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/what-is-global-keyword-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Mon, 20 May 2024 04:30:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716054450051/8e8077cb-43cf-4e89-aa17-70254409a368.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Python, variables can be declared in two main scopes: <strong>global</strong> and <strong>local</strong>. Global variables are accessible from anywhere in the code, while local variables are only accessible within the function or block where they are defined.</p>
<p>Python has the <code>"global"</code> keyword, which allows users to modify global variables from within the local scope.</p>
<h2 id="heading-what-is-global-keyword">What is global Keyword?</h2>
<p>Let's understand with an example.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Example of "global" keyword</span>

<span class="hljs-comment"># Global variable</span>
var = <span class="hljs-string">"declared as global"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">modify_var</span>():</span>
    <span class="hljs-comment"># Function's scope</span>
    <span class="hljs-keyword">global</span> var
    <span class="hljs-comment"># Modified the global variable "var"</span>
    var = <span class="hljs-string">"modified global"</span>
    print(var)

modify_var()
print(var)
</code></pre>
<p>In this example, the global variable <code>var</code> is defined first, followed by the function <code>modify_var()</code>.</p>
<p>Inside the <code>modify_var()</code> function, the <code>global var</code> statement is used to reference the global variable <code>var</code> in the function's scope and then the variable <code>var</code> is modified and printed.</p>
<p>The function is then called. Upon running the code, you'll get the following result.</p>
<pre><code class="lang-bash">modified global
modified global
</code></pre>
<p>You can observe that the global variable <code>var</code> is modified.</p>
<p>In conclusion, <strong>the</strong> <code>global</code> <strong>keyword is used to reference and modify a global variable within the scope of a function</strong>.</p>
<h2 id="heading-not-using-global-keyword">Not Using global Keyword</h2>
<p>What happens if you do not use the <code>global</code> keyword and attempt to modify a global variable within the local scope?</p>
<pre><code class="lang-python"><span class="hljs-comment"># Global variable</span>
var = <span class="hljs-string">"declared as global"</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">modify_var</span>():</span>
    <span class="hljs-comment"># Function's scope</span>
    <span class="hljs-comment"># Trying to modify the global variable "var"</span>
    var = <span class="hljs-string">"modified global"</span>
    print(var)

modify_var()
print(var)
</code></pre>
<p>In this example, the <code>global var</code> statement is removed from the function and an attempt is made to modify the variable <code>var</code>.</p>
<pre><code class="lang-bash">modified global
declared as global
</code></pre>
<p>You can observe that the global variable <code>var</code> remains unchanged.</p>
<h2 id="heading-making-local-variable-a-global-one">Making Local Variable a Global One</h2>
<p>The <code>global</code> keyword can also be used to create a global variable in the local context.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">separate</span>():</span>
    text = <span class="hljs-string">"Geek Python"</span>
    print(text.split(<span class="hljs-string">" "</span>))

separate()
print(text)
</code></pre>
<p>In this example, the <code>text</code> variable is declared within the <code>separate()</code> function and has scope within the function only.</p>
<p>The <code>text</code> variable is being accessed outside of the function scope. This will result in an error.</p>
<pre><code class="lang-bash">[<span class="hljs-string">'Geek'</span>, <span class="hljs-string">'Python'</span>]
Traceback (most recent call last):
  ...
    <span class="hljs-built_in">print</span>(text)
          ^^^^
NameError: name <span class="hljs-string">'text'</span> is not defined. Did you mean: <span class="hljs-string">'next'</span>?
</code></pre>
<p>When you add a global statement just above the <code>text</code> variable, it becomes the global variable, which may be accessed from anywhere in the code.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">separate</span>():</span>
    <span class="hljs-keyword">global</span> text   <span class="hljs-comment"># Added global stmt</span>
    text = <span class="hljs-string">"Geek Python"</span>
    print(text.split(<span class="hljs-string">" "</span>))

separate()
print(text)
</code></pre>
<p>When you run the code, you'll get the value stored in the <code>text</code> variable.</p>
<h2 id="heading-assigning-value-to-the-global-variable-within-local-scope">Assigning Value to the Global Variable Within Local Scope</h2>
<p>Consider the following example which attempts to change the global variable within the local scope without using the global statement.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Global variable</span>
initial = <span class="hljs-number">2</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">increment</span>():</span>
    <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
        <span class="hljs-comment"># Assigning value to the global var in local context</span>
        initial += x

increment()
print(initial)
</code></pre>
<p>A global variable named <code>initial</code> is declared and initialized with the value 2.</p>
<p>The function named <code>increment()</code> increments the global variable <code>initial</code>. The function is then called and the value of the <code>initial</code> variable is printed.</p>
<p>When you run the code, you'll get the following result.</p>
<pre><code class="lang-bash">Traceback (most recent call last):
  ...
    increment()
  ...
    initial += x
    ^^^^^^^
UnboundLocalError: cannot access <span class="hljs-built_in">local</span> variable <span class="hljs-string">'initial'</span> <span class="hljs-built_in">where</span> it is not associated with a value
</code></pre>
<p>The error message indicates that the local variable <code>"initial"</code> cannot be accessed. Python interprets the function's <code>initial</code> variable as a new local variable, which is why the code failed to locate the <code>initial</code> variable within the function's scope and returned an error.</p>
<p>However, when you add a global statement (<code>global initial</code>) within the function, Python will know that it is now referencing the existing global variable within the local scope.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Global variable</span>
initial = <span class="hljs-number">2</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">increment</span>():</span>
    <span class="hljs-keyword">global</span> initial
    <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
        <span class="hljs-comment"># Assigning value to the global var in local context</span>
        initial += x

increment()
print(initial)
</code></pre>
<p>You won't get an error when you run the code as the global statement has been added to the function scope.</p>
<pre><code class="lang-bash">47
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The <code>global</code> keyword can be used to reference and modify an existing global variable within a local scope. If the global variable does not already exist, the <code>global</code> keyword can be used to create it within the local scope of a function.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/yield-keyword-in-python">Yield Keyword in Python with Examples</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/positional-and-keyword-arguments-in-python">Best Practices: Positional and Keyword Arguments in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/python-getitem-method">Python's __getitem__ method</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/build-websocket-server-and-client-using-python">Create a WebSocket Server and Client in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/mysql-database-in-python">Create and Interact with MySQL Database in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/asterisk-in-python">Understanding the Different Uses of the Asterisk(*) in Python</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item><item><title><![CDATA[Type Hinting in Python]]></title><description><![CDATA[Python is a dynamically typed language, meaning you do not need to specify the type of variables, parameters or return values. This is determined during program execution based on the values assigned to the variable or passed as the argument.
Python ...]]></description><link>https://teamgeek.geekpython.in/type-hint-in-python</link><guid isPermaLink="true">https://teamgeek.geekpython.in/type-hint-in-python</guid><category><![CDATA[Type Hinting]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Sachin Pal]]></dc:creator><pubDate>Mon, 22 Apr 2024 11:02:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1713499047851/83565f54-6c8f-447a-bf74-2c26399bc1d5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python is a dynamically typed language, meaning you do not need to specify the type of variables, parameters or return values. This is determined during program execution based on the values assigned to the variable or passed as the argument.</p>
<p>Python introduced type hints or static typing with version 3.5, allowing developers to declare the data type of variables, parameters, etc.</p>
<h2 id="heading-what-is-type-hint">What is Type Hint?</h2>
<pre><code class="lang-python">x: int = <span class="hljs-number">5</span>
y: str = <span class="hljs-string">"5"</span>
</code></pre>
<p>In this example, the variable <code>x</code> expects an integer value while the variable <code>y</code> expects a string value.</p>
<p>This is called type hint or static typing where you specify the expected data type for a variable, parameter or return value of a function.</p>
<p>Python has a different way of declaring type hints for the variables, return values, collections, etc.</p>
<p>Consider the following example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">circle</span>(<span class="hljs-params">radius: float</span>) -&gt; str:</span>
    area = <span class="hljs-number">3.14</span> * radius ** <span class="hljs-number">2</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"Area of circle: <span class="hljs-subst">{area}</span>"</span>
</code></pre>
<p>In this example, the function circle accepts an argument <code>radius</code> which is expected to be a float value as indicated by type hint <code>radius: float</code>, and the return value of this function is expected to be a string, as indicated by the <code>-&gt; str</code> hint.</p>
<h2 id="heading-performing-a-check">Performing a Check</h2>
<p>What if you pass the argument of a different type which is not expected? Consider the function below:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">date</span>(<span class="hljs-params">dd: str, mm: str, yyyy: str</span>) -&gt; str:</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">f"Current Date: <span class="hljs-subst">{dd}</span>-<span class="hljs-subst">{mm}</span>-<span class="hljs-subst">{yyyy}</span>"</span>

curr_date = date(<span class="hljs-number">22</span>, <span class="hljs-number">9</span>, <span class="hljs-number">2024</span>)  <span class="hljs-comment"># expected 'str' got 'int'</span>
print(curr_date)
</code></pre>
<p>The function <code>date()</code> accepts three arguments and expects all of them to be a string value, however, integer values are supplied when the function is called.</p>
<p>What do you think? Will this program throw an error? Well, it looks like but Python or specifically interpreter completely ignores the type hints as this is not its purpose.</p>
<pre><code class="lang-bash">Current Date: 22-9-2024
</code></pre>
<p>The type of arguments was decided in the runtime that is why no error is thrown, however, you may see a warning in your IDE or code editor.</p>
<h2 id="heading-annotating-multiple-return-types">Annotating Multiple Return Types</h2>
<p>In this section, you'll learn how to annotate multiple return types for a single value of alternative types and multiple values of different types.</p>
<h3 id="heading-alternative-types-for-a-return-value">Alternative Types for a Return Value</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str</span>) -&gt; str | <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Item added in the cart"</span>
</code></pre>
<p>The function <code>cart()</code> accepts an argument item and returns <code>None</code> if it is not supplied, otherwise, it returns a string.</p>
<p>To represent multiple return types for a function, the (<code>|</code>) pipe can be used. It means either <code>str</code> or <code>None</code>. So, when you call the function, it indicates that the return value of the function can be a <code>str</code> or <code>None</code>.</p>
<p>You can also use <code>typing.Union</code> to accomplish the same task you've done using the (<code>|</code>).</p>
<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">cart</span>(<span class="hljs-params">item: str</span>) -&gt; Union[<span class="hljs-keyword">None</span>, str]:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Item added in the cart"</span>
</code></pre>
<p>The <code>Union[None, str]</code> is equivalent to <code>None | str</code>. <code>None | str</code> is a shorthand and it is a recommended way.</p>
<h3 id="heading-multiple-return-values-of-different-types">Multiple Return Values of Different Types</h3>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; dict[str, int] | <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}
</code></pre>
<p>The function <code>cart()</code> has been updated to accept an additional argument <code>quantity</code> and returns <code>None</code> if any of the arguments are left empty, otherwise, it returns a dictionary containing a key (<code>str</code>) and value (<code>int</code>).</p>
<p>If you look at the type hint for the return value, this time different types (<code>str</code> and <code>int</code>) are expected to return in a dictionary (<code>dict</code>).</p>
<p>You can do this in the following way.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union, Dict

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; Union[Dict[str, int], <span class="hljs-keyword">None</span>]:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}
</code></pre>
<p>You can use <code>Mapping</code> instead of <code>Dict</code> to represent the dictionary.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Union, Mapping

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; Union[Mapping[str, int], <span class="hljs-keyword">None</span>]:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}
</code></pre>
<p>But all this seems a bit verbose so you can go for shorthand syntax.</p>
<h2 id="heading-type-hinting-functions">Type Hinting Functions</h2>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Callable

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_cart</span>(<span class="hljs-params">
        func: Callable[[str, int], dict[str, int]],
        item: str,
        quantity: int
</span>) -&gt; dict[str, int]:</span>
    <span class="hljs-keyword">return</span> func(item, quantity)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; dict[str, int] | <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}
</code></pre>
<p>The function <code>apply_cart()</code> accepts a callable object (which can be a function or any other callable object) and two arguments (<code>item</code> and <code>quantity</code>) and returns a dictionary containing the key and value.</p>
<p>The <code>Callable</code> type hint provides a list of arguments (<code>[str, int]</code>) that the callable object accepts. In this case, <code>func()</code> expects strings and integers. Callable's second parameter is the return value (<code>dict[str, int]</code>), which is a dictionary.</p>
<p>The second function, <code>cart()</code>, is identical to the previous example and returns a dictionary if everything is correct.</p>
<pre><code class="lang-python">cart_item = apply_cart(cart, <span class="hljs-string">"Mouse"</span>, <span class="hljs-number">2</span>)
print(cart_item)
--------------------
{<span class="hljs-string">'Mouse'</span>: <span class="hljs-number">2</span>}
</code></pre>
<p>The <code>apply_cart()</code> function is invoked with the <code>cart</code> (a function) and two arguments (<code>'Mouse'</code>, <code>2</code>).</p>
<p>The <code>apply_cart()</code> function calls the <code>cart()</code> function with the given arguments and returns a result.</p>
<p>Here's an optimisation, if you have many arguments of different types, you can use <strong>ellipsis</strong> (<code>...</code>) rather than passing different input types.</p>
<p>The ellipsis literal (<code>...</code>) indicates that callable can accept any arbitrary list of arguments.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Callable
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypeVar, Any

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

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_cart</span>(<span class="hljs-params">
        func: Callable[..., T],
        *args: Any
</span>) -&gt; T:</span>
    <span class="hljs-keyword">return</span> func(*args)
</code></pre>
<p>The <code>apply_cart()</code> function has been updated and now accepts an arbitrary list of arguments of any type (<code>[..., T]</code>) as well as variadic argument (<code>*args</code>) of any type (<code>Any</code>).</p>
<p>The first parameter in the <code>Callable</code> is an ellipsis (<code>...</code>), suggesting that any arbitrary parameter list is permitted.</p>
<p>The second parameter is a <strong>type variable</strong> (<code>T = TypeVar("T")</code>) that can work with any type. It indicates that the callable can accept any type and return an element of that type.</p>
<p>You can also use a <strong>parameter specification variable</strong> (<code>ParamSpec</code>) instead of an ellipsis to make callable objects accept any number of positional or keyword arguments.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Callable
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypeVar, ParamSpec

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

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_cart</span>(<span class="hljs-params">
        func: Callable[P, T],
        *args: P.args
</span>) -&gt; T:</span>
    <span class="hljs-keyword">return</span> func(*args)
</code></pre>
<p>In this case, the first parameter of <code>Callable</code> is a <strong>parameter specification variable</strong> (<code>P = ParamSpec("P")</code>) indicating arbitrary list of arguments is acceptable. The second parameter (<code>T</code>) indicates that any type is acceptable.</p>
<p>The function <code>apply_cart()</code> also accepts a variadic argument (<code>*args</code>) of type <code>P.args</code> that represents a tuple of any number and type of positional arguments. To annotate <code>**kwargs</code>, <code>P.kwargs</code> must be used that represents the mapping of keyword parameters to their values.</p>
<p>Instead of using the ellipsis literal, you may now utilise <code>ParamSpec</code> and <code>TypeVar</code> to enable callable objects to accept any number of positional or keyword arguments of any type.</p>
<p>The code is further updated by adding <code>**kwargs</code>, which allows the function to accept keyword arguments of arbitrary length.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Callable
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypeVar, ParamSpec

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

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">apply_cart</span>(<span class="hljs-params">
        func: Callable[P, T],
        *args: P.args,
        **kwargs: P.kwargs
</span>) -&gt; T:</span>
    <span class="hljs-keyword">return</span> func(*args, **kwargs)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; dict[str, int] | <span class="hljs-keyword">None</span>:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}

cart_item = apply_cart(cart, <span class="hljs-string">"Mouse"</span>, quantity=<span class="hljs-number">2</span>)
print(cart_item)
</code></pre>
<h2 id="heading-type-hinting-iterables">Type Hinting Iterables</h2>
<p>Consider the following function that takes a list of names and sorts them in ascending order.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sort_student</span>(<span class="hljs-params">names: list[str]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    sorting = sorted(names)
    <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> sorting:
        print(name)

n = [<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>]
sort_student(n)
</code></pre>
<p>The <code>list[str]</code> type is used to type hint the parameter <code>names</code> to indicate that it expects a list of strings.</p>
<p>But what if you want <code>names</code> to be a type <strong>tuple</strong> or <strong>set</strong> instead? You need to refactor your code. In this case, you need to change the type in one location, however, this might be hard in complex and big projects.</p>
<p>You can use the type <code>Iterable</code> to make the function accept any iterable object.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Iterable

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sort_student</span>(<span class="hljs-params">names: Iterable[str]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    sorting = sorted(names)
    <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> sorting:
        print(name)

n1 = (<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>) <span class="hljs-comment"># No error</span>
n2 = [<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>] <span class="hljs-comment"># No error</span>
n3 = {<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>} <span class="hljs-comment"># No error</span>
</code></pre>
<h2 id="heading-type-aliases-for-better-readability">Type Aliases for Better Readability</h2>
<p>The complex type hints for callable objects like in the above case, arguments, and return values of the functions kind of feel cumbersome to write.</p>
<p>Why can't simplify the complex type by giving them an <strong>alias</strong>(name)? You can create an alias for the type in the same way you would create a variable.</p>
<pre><code class="lang-python">type ReturnCart = dict[str, int] | <span class="hljs-literal">None</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cart</span>(<span class="hljs-params">item: str, quantity: int</span>) -&gt; ReturnCart:</span>
    <span class="hljs-keyword">if</span> item == <span class="hljs-string">""</span> <span class="hljs-keyword">or</span> quantity == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
    <span class="hljs-keyword">return</span> {item: quantity}

cart_item = apply_cart(cart, <span class="hljs-string">"Mouse"</span>, quantity=<span class="hljs-number">2</span>)
print(cart_item)
</code></pre>
<p>In the above example, an alias <code>ReturnCart</code> is created and contains the type of return value (<code>dict[str, int] | None</code>).</p>
<p>The alias is defined with the <a target="_blank" href="https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords">soft keyword</a><a target="_blank" href="https://docs.python.org/3/reference/simple_stmts.html#type"><code>type</code></a>, which creates an instance of <a target="_blank" href="https://docs.python.org/3/library/typing.html#typing.TypeAliasType"><code>TypeAliasType</code></a>. This keyword was added in Python 3.12. If you are using an older version of Python, you can choose an alternate method.</p>
<p>Type aliases can also be created like you would create a variable using a simple assignment.</p>
<pre><code class="lang-python">ReturnCart = dict[str, int] | <span class="hljs-literal">None</span>
</code></pre>
<p>To clarify, you can mark it with <code>TypeAlias</code> to explicitly show this as a type alias, not a simple variable.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> TypeAlias

ReturnCart: TypeAlias = dict[str, int] | <span class="hljs-literal">None</span>
</code></pre>
<p>The methods described above will assist you in simplifying complex types, and the key benefit is that you will only need to edit the type in one spot, eliminating the need for refactoring.</p>
<p>Another advantage of using type aliases is that they can be reused in other portions of your code, which improves code readability.</p>
<h2 id="heading-type-checker-tools">Type Checker Tools</h2>
<p>Python entirely ignores type hints and determines the type of variables, function arguments, and return values at runtime.</p>
<p><a target="_blank" href="https://mypy.readthedocs.io/en/stable/getting_started.html#">Mypy</a>, a popular third-party tool, can enforce type-checking in Python. Since it is a third-party tool, you must install it using the following command.</p>
<pre><code class="lang-python">python -m pip install mypy
</code></pre>
<p>This will provide you access to the <code>mypy</code> command to type-check your program.</p>
<h3 id="heading-static-type-checking-using-mypy">Static Type Checking Using Mypy</h3>
<p>The function <code>sort_student()</code> takes an iterable object and sorts the student names in ascending order. Save this function to a file, such as <code>student.py</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># student.py</span>
<span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Iterable

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sort_student</span>(<span class="hljs-params">names: Iterable[str]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    sorting = sorted(names)
    <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> sorting:
        print(name)

n1 = (<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>)
sort_student(n1)
</code></pre>
<p>To type check your program using <code>mypy</code>, enter the command <code>mypy</code> followed by the file name you want to check in the terminal.</p>
<pre><code class="lang-python">&gt; mypy student.py 
Success: no issues found <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> source file
</code></pre>
<p>The type checker identified no errors. One thing you may have noticed is that the code contains the function call (<code>sort_student(n1)</code>), which should have created the output, but there was none in the terminal except the message created by <code>mypy</code>.</p>
<p>This means that <code>mypy</code> does not execute your code, instead, it examines if the values match the expected type based on the type hints.</p>
<p>What if you made a mistake and the actual values do not match the expected type?</p>
<pre><code class="lang-python"><span class="hljs-comment"># student.py</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sort_student</span>(<span class="hljs-params">names: list[str]</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
    sorting = sorted(names)
    <span class="hljs-keyword">for</span> name <span class="hljs-keyword">in</span> sorting:
        print(name)

n1 = (<span class="hljs-string">"Gojo"</span>, <span class="hljs-string">"Yuta"</span>, <span class="hljs-string">"Yuji"</span>, <span class="hljs-string">"Megumi"</span>)
sort_student(n1)
</code></pre>
<p>This function expects a list of strings but the tuple was passed. If you now check your code, it will generate the following error.</p>
<pre><code class="lang-python">&gt; mypy student.py
student.py:<span class="hljs-number">8</span>: error: Argument <span class="hljs-number">1</span> to <span class="hljs-string">"sort_student"</span> has incompatible type <span class="hljs-string">"tuple[str, str, str, str]"</span>; expected <span class="hljs-string">"list[str]"</span>  [arg-type]
Found <span class="hljs-number">1</span> error <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> file (checked <span class="hljs-number">1</span> source file)
</code></pre>
<p>Mypy has identified the error on line number 8 saying that the argument passed to <code>sort_student()</code> has an incompatible type <code>tuple[str, str, str, str]</code>, it is expected to be a <code>list[str]</code>.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><a target="_blank" href="https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html">Type cheat sheet</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p><strong>Type hints</strong> are optional in Python but they can be used to make the code more readable and using type hints can avoid possible bugs in your code.</p>
<p>In this article, you've learned:</p>
<ul>
<li><p>Implementing type hints</p>
</li>
<li><p>Alternative types for single data and different types for multiple values using pipe (<code>|</code>) and <code>Union</code></p>
</li>
<li><p><code>Callable</code> type for type hinting functions</p>
</li>
<li><p>Ellipsis (<code>...</code>) and <code>TypeVar</code> in <code>Callable</code> type to make a callable object accept an arbitrary list of arguments of any type</p>
</li>
<li><p><code>ParamSpec</code> instead of an ellipsis with <code>TypeVar</code> in Callable type to make a good combination for a callable object accepting an arbitrary list of arguments of any type</p>
</li>
<li><p><code>Iterable</code> type for type hinting iterable objects</p>
</li>
<li><p>Type aliases to simplify complex type</p>
</li>
<li><p><strong>Mypy</strong> for type checking in Python</p>
</li>
</ul>
<p>There is <a target="_blank" href="https://docs.python.org/3/library/typing.html#">much more</a> you can do with type hints in Python.</p>
<hr />
<p>🏆<strong>Other articles you might be interested in if you liked this one</strong></p>
<p>✅<a target="_blank" href="https://geekpython.in/positional-and-keyword-arguments-in-python">Best Practices: Positional and Keyword Arguments in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/decorators-in-python">Decorators in Python and How to Create a Custom Decorator</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/build-websocket-server-and-client-using-python">Create a WebSocket Server and Client in Python</a>.</p>
<p>✅<a target="_blank" href="https://geekpython.in/mysql-database-in-python">Create and Interact with MySQL Database in Python</a></p>
<p>✅<a target="_blank" href="https://geekpython.in/asterisk-in-python">Understanding the Different Uses of the Asterisk(*) in Python</a>?</p>
<p>✅<a target="_blank" href="https://geekpython.in/yield-keyword-in-python">Yield Keyword in Python with Examples</a>?</p>
<hr />
<p><strong>That's all for now</strong></p>
<p><strong>Keep Coding✌✌</strong></p>
]]></content:encoded></item></channel></rss>