<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Desert Thunder - Medium]]></title>
        <description><![CDATA[A blog to give you the skills to be the best engineer and programmer you can be. - Medium]]></description>
        <link>https://medium.com/desertthunder?source=rss----a8433bf97e13---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Desert Thunder - Medium</title>
            <link>https://medium.com/desertthunder?source=rss----a8433bf97e13---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 05:31:50 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/desertthunder" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Playing Pokémon Legends ZA]]></title>
            <link>https://medium.com/desertthunder/playing-pok%C3%A9mon-legends-za-9f5f4b63187a?source=rss----a8433bf97e13---4</link>
            <guid isPermaLink="false">https://medium.com/p/9f5f4b63187a</guid>
            <category><![CDATA[pokemon-legends-z-a]]></category>
            <category><![CDATA[pokemon]]></category>
            <category><![CDATA[nintendo-switch]]></category>
            <dc:creator><![CDATA[Owais]]></dc:creator>
            <pubDate>Sun, 16 Nov 2025 17:41:03 GMT</pubDate>
            <atom:updated>2025-11-16T17:41:03.200Z</atom:updated>
            <content:encoded><![CDATA[<p>Every November since 2007, I’ve played a Pokémon game. My family never did much during the Thanksgiving holiday, so I’d usually burn through a game then, even the year I first got Stardew Valley. The need for it was a little different this time around, because I really needed this Pokémon game for my sanity. The job market and overall state of the country (I’m in the southern US) have been eating me alive. Things do feel a little hopeless.</p><p>I’d say by and large, playing this game has helped. It didn’t knock down my productivity too much. Also, I <strong>really</strong> think Zygarde is a Digimon. I believe this so strongly that I made a silly little <a href="https://bsky.app/profile/did:plc:xg2vq45muivyy3xwatcehspu/post/3m5nea3gsvk2a">graphic</a> to explain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WBoEcB3t4ppku2aQ" /><figcaption>A flowchart explaining the digivolution sequence of the alleged Pokemon, Zygarde</figcaption></figure><p>I’m a biased Pokémon stan and really loved Scarlet &amp; Violet (SV) despite the performance issues. Legends Arceus (PLA) was really fun, but felt a little hollow. Hisui had this sense of scale, but the design was just so plain and repetitive. ZA suffers from that a little bit as well, with little variation between buildings and streets. It’s often hard to orient yourself to your location. It’s a little disappointing given that the game takes place in a single city, and it would make a lot of sense to see some variation. PLA had different weather and topography that served it well. You don’t really feel this in ZA until you go to the sewers a little over halfway through the game.</p><p>On a more positive note, the graphical fidelity and performance are great on my OG Switch. The battle transitions are seamless, and the moves look great. There really doesn’t feel like much of a difference between the overworld and battles. I do miss the transition into battles that PLA had, but it fit the game’s vibe. The real-time combat is fantastic.</p><p>The new mega evolutions are absurd and fun like they’ve always been.</p><p>I wasn’t too invested in the story, which was an issue I had with the original Kalos region offerings. This region really seems like vibes first story second. I’m curious about how a return to Unova will feel. Those games were my favorites. How can you not think Haxorus is the coolest Pokémon ever?</p><p>I’ve still got a little way to go as far as beating it. I completed the wild zones, but not all the research requests. I think I might actually have to interact with another person to do a bunch of trade evolutions. First-world problem meets GameFreak removing a feature (think link cable evolution item in PLA) between releases.</p><p>This game improves on both Scarlet &amp; Violet and Legends: Arceus, refining their core innovations. GameFreak has faced more scrutiny and fan criticism (mostly deserved) because of how these games look and the little change between them. I’ve come to terms with the slow pace of progress between releases. That’s definitely not the <em>ideal</em> way to review stuff, but between Pokémon games and Marvel Cinematic Universe movies, I’m less critical than most. They bring me joy and don’t insult my intelligence. Anyway, I think if you’ve ever enjoyed a Pokémon game, you’ll like this one. If you’re over 10, this won’t tip the scales in my opinion.</p><p>Maybe I’ll start reviewing things and posting them here. I should probably finish whichever of Brilliant Diamond or Shining Pearl I own.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9f5f4b63187a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/desertthunder/playing-pok%C3%A9mon-legends-za-9f5f4b63187a">Playing Pokémon Legends ZA</a> was originally published in <a href="https://medium.com/desertthunder">Desert Thunder</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Please Clap]]></title>
            <link>https://medium.com/desertthunder/please-clap-07139944cf50?source=rss----a8433bf97e13---4</link>
            <guid isPermaLink="false">https://medium.com/p/07139944cf50</guid>
            <category><![CDATA[scope-creep]]></category>
            <category><![CDATA[elm]]></category>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <dc:creator><![CDATA[Owais]]></dc:creator>
            <pubDate>Tue, 11 Feb 2025 05:17:21 GMT</pubDate>
            <atom:updated>2025-02-11T05:17:21.355Z</atom:updated>
            <content:encoded><![CDATA[<p>My <a href="https://stormlightlabs.org/">company</a> uses two languages right now: Dart &amp; Rust. Dart with Flutter for mobile applications and Rust for command-line and GUI applications. Since it is just me for the foreseeable future, I’ve been focusing on cross-platform tools that challenge me. It isn’t exactly the most practical way to ship but I’d like to use company time to build my knowledge and add to my toolbox. In the month or so I’ve been using these two languages I’m reminded that it is hard to handle context switching between projects and how much I appreciate a team with a more product focused member. The only person that can stop <a href="https://en.wikipedia.org/wiki/Scope_creep">scope creep</a> right now is me.</p><p>I have also learned Rust is a harder language to pick up than Dart, and in order to really learn Rust, I have to slow down and use the resources available to me. The way I learned Go was by doing things I’d usually do in Python with a small go script. My approach these days is to “read the manual” and then get started. This has been helpful for understanding concepts around Rust’s ownership system (you can read my notes <a href="https://desertthunder.github.io/garden/programming/rust/ownership/">here</a>). Over time I’m going through each chapter of the Rust book (<a href="https://amzn.to/3EvBEey">print</a> or <a href="https://doc.rust-lang.org/book/">online</a>) and taking detailed notes for my digital garden. Hopefully they can help you review the material if its hard to grasp or remember. All of that aside, my point is that Rust requires that I slow down a little bit and build smaller projects while continuing to build features for my main projects. I’m working on a small CLI using the <a href="https://docs.rs/clap">clap</a> package. It’s like being a junior engineer again. I would power through tasks during the day and in the evenings try to get a deeper understanding of what was asked of me.</p><p>I find Dart to be way easier. Rust is interesting but I’m not having fun quite yet. This is likely due to Dart’s familiarity and flexibility. It shares a lot with languages used commonly in application development, like ES5 JavaScript and Java.</p><p>Plus the developer experience for Flutter is fantastic. I really appreciate the hot reload and ability to easily test my application on both platforms. Sure, you can quickly whip up features in a web app, but there’s something magical about seeing an app hot reload on your phone or in an iOS simulator. I’ve been using the material widgets for <a href="https://github.com/stormlightlabs/soulbloom">Soulbloom</a>, and they take a lot of the overhead out of the process of writing client side code.</p><p>Learning React was similar for me. I started learning modern web development in earnest after I felt that I had a firm grasp of JavaScript. State machine patterns were brand new and difficult to wrap my head around. “UI as a function of state¹” is the key pattern that was being discussed and taught as the ecosystem moved away from lifecycle methods into hooks.</p><p>Designing an application and mapping out the state is challenging. <a href="https://amzn.to/40UD3mi">Elm</a>’s usage of messages² to describe the way an action (sort of like redux action types³) mutates state is great for building mental models. <a href="https://iced.rs/">Iced</a> uses the Elm architecture, which has been great for conceptualizing and writing my application. The limiting factor remains my knowledge of Rust.</p><p>As I continue to build and learn, I want to express more gratitude towards <a href="https://blakewatson.com/">Blake Watson</a>. He has a phenomenal post about <a href="https://blakewatson.com/journal/finishing-side-projects/">finishing</a> side projects. You should give it a read if you struggle to finish your projects.</p><p>1: <a href="https://docs.flutter.dev/app-architecture/concepts#ui-is-a-function-of-immutable-state">https://docs.flutter.dev/app-architecture/concepts#ui-is-a-function-of-immutable-state</a> <br>2: <a href="https://guide.elm-lang.org/architecture/">https://guide.elm-lang.org/architecture/</a><br>3: <a href="https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow#actions">https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow#actions</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=07139944cf50" width="1" height="1" alt=""><hr><p><a href="https://medium.com/desertthunder/please-clap-07139944cf50">Please Clap</a> was originally published in <a href="https://medium.com/desertthunder">Desert Thunder</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Need More Time]]></title>
            <link>https://medium.com/desertthunder/need-more-time-52057f92ca6a?source=rss----a8433bf97e13---4</link>
            <guid isPermaLink="false">https://medium.com/p/52057f92ca6a</guid>
            <category><![CDATA[tailwind]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[alpinejs]]></category>
            <dc:creator><![CDATA[Owais]]></dc:creator>
            <pubDate>Sat, 08 Feb 2025 07:57:13 GMT</pubDate>
            <atom:updated>2025-02-08T07:57:12.922Z</atom:updated>
            <content:encoded><![CDATA[<p>It honestly feels like there are not enough hours in the day. I watched a video by Dreams of Code where <a href="https://www.youtube.com/watch?v=vLB7r8neQvE">he talked</a> about Alpine.js. I can’t really remember much about it besides the fact that it has a very descriptive and accurate title. I have proof too! Today I replaced my root github page with an <a href="https://desertthunder.github.io/">updated</a> start page. This is what I spent my afternoon doing in between looking for jobs. It was a bit like watching Netflix while studying. Which thing are you <em>really</em> doing? Why? Anytime I attempted to do it was because studying wasn’t fun but How I Met Your Mother hadn’t yet ended. Anyways I’ll walk through some of the decisions I made with the first iteration.</p><h3>Building a Start Page</h3><p>Here is a snippet from the main <a href="https://github.com/desertthunder/desertthunder.github.io/blob/main/lib/js/index.js">script</a> for the page/app:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*285830b6mnR5M084TLJyvg.png" /><figcaption>Some data &amp; JSDoc types</figcaption></figure><p>So here I use JSDoc types because I didn’t feel like dealing with TypeScript today. The point of Alpine is to make interactivity simple, and all I was building was a web page with a few columns of links (I was inspired by this¹) and a pleasing color scheme². I took this hardcoded array of links and rendered them using the <strong>x-for </strong>directive. An easy way to iterate.</p><p>The slightly more challenging aspect of interactivity for me was using the <strong>$store</strong> magic. Basically I wanted the sidebar visibility to be available globally and spent a long time figuring out why I couldn’t get it to work. It was because you define the initial value of that particular slice with a value, not a function. This, and the dark mode toggle with a little bit of animation are so common in web apps nowadays and its nice that you can just whip it up with a few lines of code.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/874/1*9BlU8u8uQtPgMU84GJnDOA.png" /><figcaption>State management in Alpine.js</figcaption></figure><p>The sidebar is polished with a few directives added to the markup:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TapEfJlGnyPQpoozmXVbRQ.png" /><figcaption>Sidebar markup with alpine directives and tailwind</figcaption></figure><p>The defaults were enough for my purposes. The documentation wisely provides some tailwind specific³ examples. My favorite thing about tailwind is the LSP. Autocomplete with icon sets is a godsend. Especially with Remix Icon. You can quickly leverage variants of an icon. Here’s how I do hover states with some icons:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mc_GQKBWCnrAuKAcx4apNg.png" /><figcaption>An icon (Remix spotify) using the hover utility</figcaption></figure><p>Though more often than not, I want colors to change when an icon is in a button so it’ll look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-3-04SvghzVZnKd-kW9DKg.png" /><figcaption>A button using the group utility.</figcaption></figure><p>If not for the LSP, I’d likely have these saved as snippets. I had a lot of fun<br>just playing around with markup today.</p><h3>Home Cooked Software</h3><p>This was all inspired by a rabbit hole that Blake sent me on[⁴]. I didn’t know<br>what a home cooked app was but I like the sentiment. Cooking is a true labor of love and I hope I can provide more joy and show love to people with my work. I’m staring at monospaced fonts all day, may as well bring some warmth to someone’s soul instead of my eye sockets.</p><p>Local first software⁵, written extensively about by Martin Kleppman (author of <a href="https://amzn.to/40Lt6aP">Designing Data Intensive Applications</a>), had a talk⁶ at their Berlin conference last year about Home Cooked Software and the concept<br>of a barefoot engineers. The central purpose of the talk was to describe the tech savvy programming adjacent person’s new power with tools like v0, ChatGPT, and <a href="https://www.tldraw.com/">TLDraw</a>. You probably know a person who doesn’t code but<br>builds the coolest spreadsheets and probably sells notion templates on gumroad. Sometimes they do learn to <a href="https://www.youtube.com/watch?v=NpUuuT_EzSs">code</a> but maybe they don’t have to in order to make cool stuff.</p><p>This doesn’t <em>really</em> pertain to me. I’m not an amazing engineer. I just do it<br>for the love of the game⁷ and can’t use AI autocomplete or AI generated code without getting upset. Robin Sloan’s <a href="https://www.robinsloan.com/notes/home-cooked-app/">notes</a> are more in line with how I’d approach this. The key here is really knowing your users. In his notes, one of them is his mother. As I’ve worked on my company’s projects, the best feedback I’ve gotten is from my friends who I know would use my stuff. I’d like for my relationship with users and my community to be a little like that mixed with a cult following (the John Green kind). I feel a lot of joy knowing when someone finds value in my work and it’s a high I chase quite relentlessly.</p><p>Thanks for reading.</p><p>1: &lt;<a href="https://afinestart.me/">https://afinestart.me/</a>&gt; by Blake Watson who I discovered googling about some of Alpine’s directives.<br>2: &lt;<a href="https://rosepinetheme.com/">https://rosepinetheme.com/</a>&gt; Rosé Pine is one of my favorite colorschemes<br>3: &lt;<a href="https://alpinejs.dev/directives/transition">https://alpinejs.dev/directives/transition</a>&gt;<br>4: &lt;<a href="https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/">https://blakewatson.com/journal/alpinejs-for-home-cooked-apps/</a>&gt;<br>5: &lt;<a href="https://localfirstweb.dev/">https://localfirstweb.dev/</a>&gt; For my money, this is *real* serverless work.<br>There’s an entire <a href="https://pglite.dev/">company</a> that recreated Postgres in <em>WASM</em>. How cool is that?<br>6: &lt;<a href="https://maggieappleton.com/home-cooked-software">https://maggieappleton.com/home-cooked-software</a>&gt; Maggie Appleton (who runs the Digital Garden <a href="https://github.com/MaggieAppleton/digital-gardeners">awesome</a>) on Github.<br>7: Okay not exactly true. I love programming but I would like to contribute<br>to an organization and collaborate with a team again. <a href="/service/mailto:info@stormlightlabs.org">Email me</a> if you’re hiring or want to collaborate!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=52057f92ca6a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/desertthunder/need-more-time-52057f92ca6a">Need More Time</a> was originally published in <a href="https://medium.com/desertthunder">Desert Thunder</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Slowing Down]]></title>
            <link>https://medium.com/desertthunder/slowing-down-c5581e5818c3?source=rss----a8433bf97e13---4</link>
            <guid isPermaLink="false">https://medium.com/p/c5581e5818c3</guid>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[100daystooffload]]></category>
            <category><![CDATA[digital-garden]]></category>
            <category><![CDATA[surrender]]></category>
            <category><![CDATA[mindfulness]]></category>
            <dc:creator><![CDATA[Owais]]></dc:creator>
            <pubDate>Thu, 06 Feb 2025 06:06:58 GMT</pubDate>
            <atom:updated>2025-02-06T06:06:58.854Z</atom:updated>
            <content:encoded><![CDATA[<p>It may sound like hyperbole, but I feel like <a href="https://amzn.to/3WIy7j1">The Untethered Soul</a> was life changing for me. I left my job back in August for personal reasons and since then, while applying for jobs, I’ve gone through a mix of self-discovery¹ and change. Facing the frequent rejections of the job hunt<br>is not an easy place to be. Up until November I was able to really grind<br>through some of that pain and keep up my routine of finding jobs, applying for jobs, and preparing for interviews, all while continuing the process of<br>building some applications for <a href="https://github.com/desertthunder/sonotabula">fun</a>.</p><p>What happened in November? Nothing major. I had interviewed with quite a few places and gotten to later rounds of the interview process but found myself getting rejected over and over and I think I just snapped. It didn’t help that my situation didn’t change and with the approaching holidays, the job market would likely slow down. I started to feel desperate and all I could think to do was try to accept my situation. I’m an engineer. Acceptance is not an innate skill I have. Everything is a problem to be solved. So I went to good old Google, which is actually just me usually searching for “best books on <em>whatever</em> reddit.” This led me to mental health and mindfulness subreddit posts about acceptance and surrender and eventually grabbing a copy of Michael A. Singer’s <a href="https://amzn.to/3WIy7j1">book</a>.</p><p>I can’t express how helpful his story has been for my psyche. He has had such a unique set of life experiences, all book-ended by challenging situations in which he chose to accept his circumstances, surrender, and go with the flow. He made it through writing a thesis and a lawsuit successfully! It seemed like magic. All he said was to surrender to the experience and let yourself experience the feelings that come up. He demonstrates something Tara Brach mentions in <a href="https://amzn.to/3CB8EBu">Radical Acceptance</a> too. Acceptance isn’t about doing nothing. You still take action, but the context surrounding it is what changes².</p><p>The experience that Singer describes of himself surrendering before writing is one my dad experienced when he first came to the states. Both of these nerds surrendered and allowed their minds to digest and synthesize information. You never know what you’ll find, and you can’t force your mind to operate the way you want it too with conscious will. This is the approach to writing these posts and my code that I feel I must take. When I am able to surrender I’m able to produce more work. Whether or not is useful or of any quality remains to be seen³. While powering through <a href="https://iced.rs/">iced</a>, I started writing a book in the <a href="https://github.com/stormlightlabs/ascdoc">repo</a>. It felt like an idea that came out of nowhere but it feels right. The library is cool but it’s documentation is famously⁴ lacking, so why not just make something myself?</p><p>Thanks for reading.</p><p>[1]: I’ll have to post my notes about the book on my digital <a href="https://desertthunder.github.io/garden">garden</a>. <br>[2]: This seems like a central theme of the FX adaptation of Shogun. I should give the book a read. The show comes with the highest recommendation from me.<br>[3]: Does it even matter? I mean, have you seen some of these HR and ATS tools? If that seems petty, it is.<br>[4]: I want to add that I mean no disrespect to the developer. Iced is incredible and its important to focus on what you feel is right. The library is good and he’s honest about the docs so what more can you ask for?</p><p>This was originally posted on my <a href="https://desertthunder.dev/blog/slowing-down/">website</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5581e5818c3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/desertthunder/slowing-down-c5581e5818c3">Slowing Down</a> was originally published in <a href="https://medium.com/desertthunder">Desert Thunder</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Asynchronous Python]]></title>
            <link>https://medium.com/desertthunder/asynchronous-python-b4634d6c2615?source=rss----a8433bf97e13---4</link>
            <guid isPermaLink="false">https://medium.com/p/b4634d6c2615</guid>
            <category><![CDATA[concurrency]]></category>
            <category><![CDATA[httpx]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[asynchronous-programming]]></category>
            <category><![CDATA[https]]></category>
            <dc:creator><![CDATA[Owais]]></dc:creator>
            <pubDate>Sun, 24 Nov 2024 08:24:00 GMT</pubDate>
            <atom:updated>2024-11-24T08:24:00.348Z</atom:updated>
            <content:encoded><![CDATA[<p>In this essay, we discuss a few different models of concurrency and how they are implemented in Python. Additionally, we address the shortcomings and advantages of each as well as dispel some myths about performance. There are also a few code samples within a sample command line interface to demonstrate the concepts illustrated here.</p><h3>Source Code</h3><p>Check out the async python demo repo <a href="https://github.com/desertthunder/async-python-demo">here</a> to play around with tasks, queues, httpx, and the MLB stats API.</p><h3>Overview</h3><p>Asynchronous programming is the process of writing code that includes events that occur independently of the main flow of the program. So a process will begin, but the interpreter will continue to execute the next steps of the program. This allows us to do multiple things at the same time. In contrast, synchronous code is executed sequentially, or a single step at a time. Each statement is executed and the computation completed before moving on to the next. It is often easy to think of the functions that are being executed like an algebraic function, in which each operation/computation occurs in a predictable order. In other words, if we imagine each operation as a task, they are performed one at a time, with one finishing completely before another the next. If they’re always performed in the same order, the implementation of later tasks can assume that previous tasks finished error-free.</p><h3>Multi-Threaded Model</h3><p>Another model for task execution, is the multi-threaded model. each task is performed in a separate thread of control, managed by the operating system kernel. On systems with multiple processors or multiple cores, run truly concurrently. This is commonly referred to as preemptive multitasking.<a href="#footnote-1">1</a></p><h3>Cooperative Multitasking &amp; GIL</h3><p>In the async model, tasks execution order is interleaved with one another in a single thread. This is simpler than the threaded case because the programmer always knows that when one task is executing, another task is not. It is called cooperative multitasking. We’ll discuss the implications of that later. For now, know that this makes an async thread subject to the Global Interpreter Lock (GIL). This is a mutex that ensures that there are no race conditions<a href="#footnote-2">2</a> . The work around for that to create multiple threads is a multithreading library.</p><p>Asynchronous programming is relevant for processes/tasks dependent on computer resources outside the CPU. For example, HTTP resources require accessing the network and opening and closing files require disk access. Synchronous statements calls are called blocking (blocking calls), because they must be executed before the next statement runs.<a href="#footnote-3">3</a></p><h3>Demo</h3><p>Here are some simple examples that ostensibly do the same things. We create a queue (remember, FIFO — first in first out), that contains tasks (simple operations), and then we iterate through the queue and execute the tasks. I’ve wrapped these in a simple click CLI. See the README in the associated <a href="https://github.com/desertthunder/async-python-demo">repo</a> for instructions on installation.</p><p>In the sync function, we create a queue and run a blocking worker function that processes tasks from the queue. We do this by using the standard library threading module and queue module, where each task is a simple pause using time.sleep(1) to simulate a blocking operation. This demonstrates how a blocking worker running in a single thread processes tasks sequentially.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AwuxIwoNecWrpIQ7.png" /></figure><p>In the async function, we create an asyncio queue and run a non-blocking worker function that processes tasks from the queue. In this case, we have two workers running concurrently, processing tasks from the queue. We&#39;re using a single-threaded event loop to run the workers concurrently. This demonstrates how non-blocking workers can run concurrently in a single thread while using the asyncio module. asyncio&#39;s sleep function is used to simulate the time it may take to complete an operation like I/O-bound tasks or network requests. This is referred to as cooperative multitasking<a href="#footnote-4">4</a>, where the event loop continues execution while the task waits for whatever resource it needs. Another example of this is done via python generators, which use yield (the task <em>yields</em> control to the loop).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vjiK_4HpuYipGrNF.png" /></figure><h3>HTTP Requests</h3><p>HTTPx is a library that gives us both an async and synchronous interface. This can provide us with a good way to demonstrate the differences between two ways to write concurrent code when the tasks are not CPU-bound. Usually you’ll see simple synchronous requests in python code executed by the requests package. The key differences in the synchronous case are the extensibility of the httpx Client object, and support for http/2. In the demo application (see cli/http.py), you can compare the time to synchronously fetch the JSON data for all 30 MLB teams versus running the tasks concurrently using the AsyncClient class from httpx.</p><h3>HTTP/1.1 vs HTTP/2</h3><p>The differences between http/1.1 and http/2, which come down to four major points: content prioritization, multiplexing, server push, and header compression<a href="#footnote-5">5</a>. Multiplexing does a lot to enhance the efficiency for developers, as it is a feature allow for a single tcp connection to be maintained between the server and client, where the client opens up multiple streams to fetch data. Server push lets the server send data to the client after sending a message detailing what content is coming. Header compression compresses redundant http header information using HPACK. When multiple requests are made, the small decreases in packet size can add up to decrease latency. Content prioritization on the other hand has more to do with web pages, as it allows the client to choose which content is loaded first (between static files like CSS or JavaScript).</p><h3>Which Concurrency Model Wins?</h3><p>A common myth is that async python code is faster than synchronous due to concurrency. As mentioned previously, this is cooperative multitasking in a <em>single</em> thread. Because it is cooperative, threads don’t have CPU distributed evenly, as execution has to be relinquished by the task itself instead of interrupted by a governor like the operating system kernel. Cal Peterson demonstrates this when benchmarking synchronous and asynchronous servers<a href="#footnote-6">6</a> He notes that async servers don’t need as many workers because they can use a single CPU. It’s the latency caused by the yielding of a task that slows them down. He notes that throughput is determined by the amount of python replaced by native code.</p><h3>Further Reading</h3><p>1. Async Python from Hackernoon (<a href="https://hackernoon.com/asynchronous-python-45df84b82434">link</a>)</p><p>2. 500 Lines or Less: A Web Crawler with Asyncio Coroutines (<a href="https://aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html">link</a>)</p><p>3. <a href="https://en.wikipedia.org/wiki/Structured_concurrency">Structured Concurrency</a>, used by an alternative to asyncio, <a href="https://trio.readthedocs.io/en/stable/">Trio</a>. The pattern here is called the “nursery pattern,” in which threads have clear entry and exit points and are encapsulated in constructs called nurseries. These ensure that the execution of the thread has completed before the process exits.</p><p>Images of code from <a href="https://carbon.now.sh/">carbon</a>.</p><p><a href="#footnote-anchor-1">1</a> Fonseca, R. (2012). Async Programming [Class handout]. Brown University, CSCI 1680.</p><p><a href="#footnote-anchor-2">2</a> “The Python GIL (Global Interpreter Lock) • Python Land Tutorial.” _Python Land_, 18 Dec. 2021, <a href="https://python.land/python-concurrency/the-python-gil.">https://python.land/python-concurrency/the-python-gil.</a></p><p><a href="#footnote-anchor-3">3</a> Grinberg, Miguel. Sync vs. Async Python: What Is the Difference? <a href="https://blog.miguelgrinberg.com/post/sync-vs-async-python-what-is-the-difference.">https://blog.miguelgrinberg.com/post/sync-vs-async-python-what-is-the-difference.</a> Accessed 24 Nov. 2024.</p><p><a href="#footnote-anchor-4">4</a> “Cooperative Multitasking.” Wikipedia, 31 Jan. 2024. Wikipedia, <a href="https://en.wikipedia.org/w/index.php?title=Cooperative_multitasking&amp;oldid=1201426758.">https://en.wikipedia.org/w/index.php?title=Cooperative_multitasking&amp;oldid=1201426758.</a></p><p><a href="#footnote-anchor-5">5</a> “HTTP/2 vs. HTTP/1.1.” Cloudflare.com, 2015, <a href="http://www.cloudflare.com/learning/performance/http2-vs-http1.1/">www.cloudflare.com/learning/performance/http2-vs-http1.1/.</a></p><p><a href="#footnote-anchor-6">6</a> “Async Python Is Not Faster.” Calpaterson.Com, 11 June 2020, <a href="https://calpaterson.com/async-python-is-not-faster.html.">https://calpaterson.com/async-python-is-not-faster.html.</a></p><p><a href="#footnote-anchor-7">7</a> Design and Internals — Trio 0.27.0+dev Documentation. <a href="https://trio.readthedocs.io/en/latest/design.html#cancel-points-and-schedule-points.">https://trio.readthedocs.io/en/latest/design.html#cancel-points-and-schedule-points.</a> Accessed 24 Nov. 2024.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b4634d6c2615" width="1" height="1" alt=""><hr><p><a href="https://medium.com/desertthunder/asynchronous-python-b4634d6c2615">Asynchronous Python</a> was originally published in <a href="https://medium.com/desertthunder">Desert Thunder</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>