<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Code Hard]]></title><description><![CDATA[Code hard, code better.]]></description><link>https://blog.codehard.net/</link><image><url>https://blog.codehard.net/favicon.png</url><title>Code Hard</title><link>https://blog.codehard.net/</link></image><generator>Ghost 5.65</generator><lastBuildDate>Mon, 20 Apr 2026 08:36:42 GMT</lastBuildDate><atom:link href="https://blog.codehard.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Python and WebSockets 101: Real-time Communication]]></title><description><![CDATA[WebSockets enable real-time, bi-directional communication between a client and a server over a single, long-lived connection.]]></description><link>https://blog.codehard.net/python-and-websockets-101/</link><guid isPermaLink="false">6523ab9c3200a202d8c2233b</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Vivien Giraud]]></dc:creator><pubDate>Mon, 09 Oct 2023 07:34:45 GMT</pubDate><media:content url="https://blog.codehard.net/content/images/2023/10/DALL-E-2023-10-09-09.34.08---Vector-imagery-of-a-vast-digital-grid-of-nodes-interlinked-by-vibrant-lines--a-visual-representation-of-WebSockets.-The-iconic-Python-logo-is-position.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction">Introduction</h2>
<img src="https://blog.codehard.net/content/images/2023/10/DALL-E-2023-10-09-09.34.08---Vector-imagery-of-a-vast-digital-grid-of-nodes-interlinked-by-vibrant-lines--a-visual-representation-of-WebSockets.-The-iconic-Python-logo-is-position.png" alt="Python and WebSockets 101: Real-time Communication"><p>WebSockets enable real-time, bi-directional communication between a client and a server over a single, long-lived connection. This article delves into how to work with WebSockets in Python, avoiding web frameworks to focus purely on the tech itself.</p>
<h2 id="table-of-contents">Table of Contents</h2>
<ol>
<li><a href="#what-are-websockets">What are WebSockets?</a></li>
<li><a href="#pythons-websockets-library">Python&apos;s <code>websockets</code> Library</a></li>
<li><a href="#building-a-simple-websocket-server">Building a Simple WebSocket Server/Client</a></li>
<li><a href="#security-concerns">Security Concerns</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ol>
<h2 id="what-are-websockets-a-namewhat-are-websocketsa">What are WebSockets? <a name="what-are-websockets"></a></h2>
<p>WebSockets are a communications protocol that provides a full-duplex communication channel over a single, long-lived TCP connection. The WebSocket Protocol was standardized by the IETF as RFC 6455 in 2011, and it has since gained widespread adoption for real-time, interactive applications where low latency and high interactivity are key requirements.</p>
<h3 id="the-websocket-handshake">The WebSocket Handshake</h3>
<p>The WebSocket connection starts with an HTTP handshake. During this phase, the client and server agree to upgrade the connection to a WebSocket connection. This is a one-time process and involves exchanging specific HTTP headers to indicate that both parties support WebSocket communication. Once the handshake is successful, the connection switches from HTTP to WebSocket, enabling a persistent, low-latency communication channel.</p>
<h3 id="full-duplex-communication">Full-duplex Communication</h3>
<p>One of the most significant advantages of WebSockets is the full-duplex communication channel it establishes. In a full-duplex channel, both the client and server can send and receive messages simultaneously without closing the connection. This is different from HTTP, where each request-response cycle involves opening and closing a connection, leading to higher latency.</p>
<h3 id="how-is-it-different-from-http">How is it Different from HTTP?</h3>
<p>HTTP is a stateless protocol, which means that each request from a client to a server is independent and may not necessarily maintain any state information between subsequent requests. WebSockets, on the other hand, maintain state and allow for a persistent connection between the client and server. This makes WebSockets ideal for applications where real-time updates and rapid data exchange are essential, such as chat applications, online gaming, and financial trading platforms.</p>
<h2 id="pythons-websockets-library-a-namepythons-websockets-librarya">Python&apos;s <code>websockets</code> Library <a name="pythons-websockets-library"></a></h2>
<p>Python has a powerful library for working with WebSockets called <code>websockets</code>, which allows you to manage WebSocket connections without the need for a web framework.</p>
<p>To install it, run:</p>
<pre><code class="language-bash">pip install websockets
</code></pre>
<h2 id="building-a-simple-websocket-serverclient-a-namebuilding-a-simple-websocket-servera">Building a Simple WebSocket Server/Client <a name="building-a-simple-websocket-server"></a></h2>
<h3 id="prerequisites">Prerequisites</h3>
<ul>
<li>Python 3.6 or higher</li>
<li><code>websockets</code> library installed (You can install it using <code>pip install websockets</code>)</li>
</ul>
<h3 id="setting-up-the-websocket-server">Setting Up the WebSocket Server</h3>
<p>You can build a simple WebSocket server using Python&apos;s <code>websockets</code> and <code>asyncio</code> libraries. Below is a sample code snippet:</p>
<pre><code class="language-python"># server.py
import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f&quot;Someone said {message}&quot;)
        await websocket.send(message)

start_server = websockets.serve(echo, &apos;localhost&apos;, 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
</code></pre>
<p>This code starts a WebSocket server on <code>ws://localhost:8765/</code>.</p>
<h3 id="creating-a-websocket-client">Creating a WebSocket Client</h3>
<p>You can also create a WebSocket client using the <code>websockets</code> library. Here&apos;s how:</p>
<pre><code class="language-python"># client.py
import asyncio
import websockets

async def hello():
    uri = &quot;ws://localhost:8765&quot;
    async with websockets.connect(uri) as websocket:
        message = input(&quot;Enter your message: &quot;)  # Get user input
        await websocket.send(message)  # Send the user&apos;s message to the WebSocket server
        response = await websocket.recv()  # Receive server response
        print(f&quot;Server Response: {response}&quot;)  # Print the server response

asyncio.get_event_loop().run_until_complete(hello())
</code></pre>
<p><strong>Run the Server</strong>: Open a terminal window, navigate to the directory where <code>server.py</code> is located, and run <code>python server.py</code>. Your WebSocket server will start at <code>ws://localhost:8765/</code>.</p>
<p><strong>Run the Client</strong>: Open another terminal window, navigate to the directory where <code>client.py</code> is located, and run <code>python client.py</code>.</p>
<p><strong>Interact</strong>: Once the client is running, you&apos;ll be prompted to enter a message. Type your message and press Enter. You should see your message echoed back by the server as &quot;Server Response: [Your Message]&quot;.</p>
<p>As you can try, not everyone connected to the server will receive the messages you send to the server, and this is we will see in a near future.</p>
<p>Such a setup offers an excellent opportunity for hands-on learning, especially in a course setting. Students tend to grasp the concept quickly, often finding it both enlightening and entertaining.</p>
<p>What makes this exercise particularly engaging is that it turns the classroom into a miniature real-time network, allowing students to immediately see the results of their code changes. The instant feedback loop not only makes the learning process more enjoyable but also fosters a sense of accomplishment.</p>
<p>It&apos;s not just about grasping the technicalities of WebSockets; it&apos;s also about witnessing the fun and immediate impact of real-time communication. This simple yet powerful exercise often becomes the highlight of the class, as students love to play around with it, sending messages, tweaking code, and exploring the possibilities of real-time data exchange.</p>
<h2 id="conclusion-a-nameconclusiona">Conclusion <a name="conclusion"></a></h2>
<p>In summary, WebSockets stand as a transformative technology that has significantly impacted the landscape of real-time communication in modern applications. Their ability to facilitate full-duplex, bi-directional interactions between clients and servers sets them apart from traditional HTTP communication methods, which are constrained by the limitations of request-response cycles.</p>
<p>Python&apos;s <code>websockets</code> library further simplifies the implementation process, offering a clean and straightforward approach to setting up both WebSocket servers and clients. This ease of use, combined with Python&apos;s robust ecosystem, makes it an excellent choice for anyone looking to delve into real-time communication features in their applications.</p>
<p>However, the powerful capabilities of WebSockets come with their own set of challenges, particularly in the realm of security. It is essential to understand the associated risks, such as potential vulnerabilities to data interception if not using WSS (WebSocket Secure), and to implement proper security measures to mitigate these risks. Issues like authentication, encryption, and rate-limiting should be high on the checklist of any developer working with WebSockets.</p>
<p>As we move towards an increasingly interconnected digital world, the importance of real-time communication can only be expected to grow. WebSockets, with their low latency and high efficiency, are likely to remain at the forefront of this evolution. Understanding the technology and how to implement it securely will, therefore, be invaluable skills for developers and IT professionals alike.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Doctest 101: Write Tests as You Write Code]]></title><description><![CDATA[When it comes to writing tests for your Python code, doctest offers an easy, readable, and Pythonic way to go about it. In this guide, we'll take a deep dive into how you can use doctest to write test cases right in your docstrings, making your code self-testing and more robust.]]></description><link>https://blog.codehard.net/doctest-101/</link><guid isPermaLink="false">651a80db3200a202d8c222ba</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Vivien Giraud]]></dc:creator><pubDate>Mon, 02 Oct 2023 09:01:56 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1516534775068-ba3e7458af70?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI0fHx0ZXN0fGVufDB8fHx8MTY5NjI0ODkwOHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h1 id="introduction">Introduction</h1><img src="https://images.unsplash.com/photo-1516534775068-ba3e7458af70?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI0fHx0ZXN0fGVufDB8fHx8MTY5NjI0ODkwOHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Doctest 101: Write Tests as You Write Code"><p>When it comes to writing tests for your Python code, <code>doctest</code> offers an easy, readable, and Pythonic way to go about it. In this guide, we&apos;ll take a deep dive into how you can use <code>doctest</code> to write test cases right in your docstrings, making your code self-testing and more robust.</p><h2 id="what-is-doctest">What is Doctest?</h2><p><code>doctest</code> is a Python standard library module that allows you to test your code by running examples embedded in your docstrings. This makes your documentation not just descriptive but also verifiable, ensuring that your code performs as expected.</p><h2 id="getting-started">Getting Started</h2><p>The basic idea behind <code>doctest</code> is to write tests as part of your docstrings. Here&apos;s a simple example:</p><pre><code class="language-python">def add(a, b):
    &quot;&quot;&quot;
    Adds two numbers together.
    
    &gt;&gt;&gt; add(2, 3)
    5
    &gt;&gt;&gt; add(-1, 1)
    0
    &quot;&quot;&quot;
    return a + b</code></pre><h2 id="running-doctests">Running Doctests</h2><h3 id="command-line-interface">Command-Line Interface</h3><p>You can run <code>doctest</code> via the command line</p><pre><code class="language-bash">python -m doctest your_module.py</code></pre><h3 id="within-your-code">Within Your Code</h3><p>You can also run <code>doctest</code> programmatically within your code:</p><pre><code class="language-python">import doctest
doctest.testmod()</code></pre><h2 id="writing-effective-tests">Writing Effective Tests</h2><h3 id="handling-exceptions">Handling Exceptions</h3><p>You can test exception-raising functions like so:</p><pre><code class="language-python">def divide(a, b):
    &quot;&quot;&quot;
    Divides a by b.
    
    &gt;&gt;&gt; divide(4, 2)
    2.0
    &gt;&gt;&gt; divide(1, 0)
    Traceback (most recent call last):
        ...
    ZeroDivisionError: division by zero
    &quot;&quot;&quot;
    return a / b</code></pre><h3 id="floating-point-numbers">Floating Point Numbers</h3><p>Be careful with floating-point numbers due to rounding errors:</p><pre><code class="language-python">def square_root(x):
    &quot;&quot;&quot;
    Returns the square root of x.
    
    &gt;&gt;&gt; square_root(4)
    2.0
    &gt;&gt;&gt; square_root(2)
    1.4142135623730951  # may vary
    &quot;&quot;&quot;
    return x ** 0.5</code></pre><!--kg-card-begin: markdown--><h3 id="floating-point-numbers-avoiding-pitfalls">Floating Point Numbers: Avoiding Pitfalls</h3>
<p>Dealing with floating-point numbers can be a bit tricky because of rounding errors and imprecise representations. However, <code>doctest</code> provides ways to manage these issues effectively.</p>
<h4 id="using-round">Using <code>round()</code></h4>
<p>One approach is to use Python&apos;s <code>round()</code> function to round the results to a specific decimal place:</p>
<pre><code class="language-python">def square_root(x):
    &quot;&quot;&quot;
    Returns the square root of x, rounded to 2 decimal places.
    
    &gt;&gt;&gt; round(square_root(2), 2)
    1.41
    &quot;&quot;&quot;
    return x ** 0.5
</code></pre>
<h4 id="string-based-comparison">String-based Comparison</h4>
<p>If you want more control over the format, you can convert the numbers to strings and then compare:</p>
<pre><code class="language-python">def square_root(x):
    &quot;&quot;&quot;
    Returns the square root of x as a string, rounded to 2 decimal places.
    
    &gt;&gt;&gt; &quot;{:.2f}&quot;.format(square_root_str(2))
    &apos;1.41&apos;
    &quot;&quot;&quot;
    return x ** 0.5
</code></pre>
<h4 id="using-mathisclose">Using <code>math.isclose()</code></h4>
<p>For more complex scenarios, you can use Python&apos;s <code>math.isclose()</code> method to check if two floating-point numbers are close enough to be considered equal:</p>
<pre><code class="language-python">import math

def test_square_root():
    &quot;&quot;&quot;
    &gt;&gt;&gt; math.isclose(square_root(2), 1.41421356237, rel_tol=1e-9)
    True
    &quot;&quot;&quot;
    pass
</code></pre>
<p>This method allows you to specify a relative tolerance level, making it highly customizable.</p>
<p>By adopting these strategies, you can write more robust and accurate tests for functions that return floating-point numbers.</p>
<!--kg-card-end: markdown--><h2 id="advanced-features">Advanced Features</h2><h3 id="verbose-mode">Verbose Mode</h3><p>You can run <code>doctest</code> in verbose mode to see a detailed log:</p><pre><code class="language-bash">python -m doctest -v your_module.py</code></pre><h3 id="skipping-tests">Skipping Tests</h3><p>To skip a test, you can add a <code>doctest: +SKIP</code> directive:</p><pre><code class="language-python">&gt;&gt;&gt; print(&quot;This will be skipped.&quot;)  # doctest: +SKIP</code></pre><h2 id="conclusion">Conclusion</h2><p><code>doctest</code> provides a quick and easy way to write tests for your Python code, right within your docstrings. It encourages good documentation practices while ensuring that your code is robust and bug-free.</p><p>So go ahead, make your docstrings work for you by making them testable!</p>]]></content:encoded></item><item><title><![CDATA[The Python Pitfall: Why You Shouldn't Modify Lists During Iteration]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction">Introduction</h2>
<p>Hello fellow Python enthusiasts! Today, we&apos;ll delve into a common pitfall that catches even experienced developers off guard: <strong>modifying a list while iterating over it</strong>. If you&apos;ve ever found yourself scratching your head over unexpected results after trying to modify a list in a loop,</p>]]></description><link>https://blog.codehard.net/the-python-pitfall-why-you-shouldnt-modify-lists-during-iteration/</link><guid isPermaLink="false">6516eb413200a202d8c2223d</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Vivien Giraud]]></dc:creator><pubDate>Fri, 29 Sep 2023 15:50:58 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1677864234709-bde08838fb9d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDkxfHxsb29wfGVufDB8fHx8MTY5NjI0ODg4Nnww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction">Introduction</h2>
<img src="https://images.unsplash.com/photo-1677864234709-bde08838fb9d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDkxfHxsb29wfGVufDB8fHx8MTY5NjI0ODg4Nnww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="The Python Pitfall: Why You Shouldn&apos;t Modify Lists During Iteration"><p>Hello fellow Python enthusiasts! Today, we&apos;ll delve into a common pitfall that catches even experienced developers off guard: <strong>modifying a list while iterating over it</strong>. If you&apos;ve ever found yourself scratching your head over unexpected results after trying to modify a list in a loop, this blog post is for you.</p>
<h2 id="the-unexpected-behavior">The Unexpected Behavior</h2>
<p>Let&apos;s start with an example, which you may have seen in a <a href="https://x.com/bbelderbos/status/1707684694362394896?ref=blog.codehard.net">tweet</a>:</p>
<pre><code class="language-python">numbers = list(range(1, 50))
for i in numbers:
    if i &lt; 20:
        numbers.remove(i)
print(numbers)
</code></pre>
<h3 id="expected-output">Expected Output</h3>
<p>You&apos;d expect that all numbers below 20 would be removed from the list, leaving you with a list ranging from 20 to 49.</p>
<h3 id="actual-output">Actual Output</h3>
<p>But what you actually get is a list like this:</p>
<pre><code class="language-python">[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, ..., 49]
</code></pre>
<p>Confused? You&apos;re not alone!</p>
<h2 id="the-culprit-list-re-indexing">The Culprit: List Re-indexing</h2>
<p>The reason behind this unexpected behavior is the way Python handles list indexing. When you remove an element from a list, the indices of the elements after the removed item are updated. This results in the loop skipping the next item every time an element is removed.</p>
<h3 id="breaking-it-down">Breaking it Down</h3>
<ul>
<li>When <code>i = 1</code>, the <code>remove()</code> method removes the first element (<code>1</code>), and all elements are shifted left.</li>
<li>Now, <code>i = 2</code>, but the loop goes to the element that was originally at index 2, which is now <code>3</code>.</li>
<li>The element <code>2</code> is skipped, and this pattern continues.</li>
</ul>
<h2 id="the-pythonic-solution-list-comprehensions">The Pythonic Solution: List Comprehensions</h2>
<p>To avoid this pitfall, you can use list comprehensions, a Pythonic way to generate lists. Here&apos;s how you can rewrite the example:</p>
<pre><code class="language-python">numbers = list(range(1, 50))
numbers = [n for n in numbers if n &gt;= 20]
print(numbers)
</code></pre>
<h3 id="output">Output</h3>
<p>As expected, this will output a list ranging from 20 to 49.</p>
<pre><code class="language-python">[20, 21, ..., 49]
</code></pre>
<h2 id="why-list-comprehensions-are-awesome">Why List Comprehensions are Awesome</h2>
<ol>
<li><strong>Readability</strong>: They make your code more concise and readable.</li>
<li><strong>Performance</strong>: List comprehensions are generally faster than traditional <code>for</code> loops, especially for larger datasets.</li>
<li><strong>Pythonic</strong>: Using list comprehensions is considered Pythonic, and it&apos;s a skill you&apos;ll see often in advanced Python code.</li>
</ol>
<h2 id="bonus-other-alternatives">Bonus: Other Alternatives</h2>
<p>While list comprehensions are great, sometimes they may not fit your needs. Here are some other ways to safely modify a list while iterating:</p>
<ol>
<li>
<p><strong>Using <code>slice()</code> to create a copy</strong>:</p>
<pre><code class="language-python">for i in numbers[:]:  # iterate over a slice copy of the entire list
    if i &lt; 20:
        numbers.remove(i)
</code></pre>
</li>
<li>
<p><strong>Iterating backwards</strong>:</p>
<pre><code class="language-python">for i in reversed(numbers):
    if i &lt; 20:
        numbers.remove(i)
</code></pre>
</li>
<li>
<p><strong>Using <code>filter()</code> function</strong>:</p>
<pre><code class="language-python">numbers = list(filter(lambda x: x &gt;= 20, numbers))
</code></pre>
</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>Modifying a list while iterating over it is a common pitfall that can lead to unexpected behavior due to the re-indexing of the list. The Pythonic way to handle such scenarios is to use list comprehensions. They are not only more readable but also generally faster.</p>
<p>Remember, Python is designed to be explicit and readable, and understanding these nuances can help you write more effective and bug-free code.</p>
<p>Happy coding!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>