[0:00] Your program freezes for a full second [0:02] on every network call. Your loop [0:04] processes earl painfully slow. Every [0:08] blocking call weighs time just sitting [0:10] and waiting. I am Mahas. Today in [0:13] episode 25, async Python, you will learn [0:17] how to run thousands of operations [0:19] concurrently without threads. We will [0:21] cover async defaf and await. How co- [0:24] routines actually work. Assentio.run and [0:28] the event loop. Assessio.Gather for [0:30] running tasks concurrently. [0:32] Assencio.create [0:34] task for scheduling background work. [0:36] Async context managers using dunder [0:38] enter and dunder exit and real [0:40] production patterns timeouts semaphors [0:43] and async iteration. By the end you will [0:46] have a full concurrent API fetcher with [0:48] a semaphore rate limit. Let's go. A [0:51] co-ine is a function defined with async [0:54] defaf. Calling it does not run the code. [0:57] It creates a co-outine object. Let's [0:59] understand what happens under the hood. [1:01] Look at the code. On the left, we define [1:03] a regular function fetch data. Calling [1:07] fetch data executes immediately and [1:10] returns a value. On the right, we define [1:13] the same function with async defaf. [1:15] Calling fetch data now returns a [1:18] co-outine object. Nothing is run yet. To [1:21] actually run it, you need a wait. But a [1:23] wait only works inside another async [1:26] function. Inside the corine, a wait [1:28] essenti. pauses this task and lets the [1:32] event loop run other code. When the [1:34] sleep finishes, execution resumes [1:37] exactly where it left off. Async defaf [1:40] creates a co-ine. A wait is what [1:42] actually runs it and gives you the [1:44] result. This pause and resume mechanism [1:46] is the foundation of every async pattern [1:49] in Python. Every async program needs an [1:52] entry point. That's essenti.run. Look at [1:55] the code. We define an async function [1:58] called main. Inside main, we print [2:00] hello. Then a weight essenti [2:03] of 1 second. This is non-blocking. The [2:06] event loop is free during this weight. [2:09] Then we print world. At the bottom, [2:12] essenti [2:15] is the entry point. It creates a brand [2:18] new event loop. runs the main co- [2:20] routine until it completes and then [2:22] closes the loop automatically. You call [2:25] essentio.run [2:26] exactly once at the top level of your [2:29] program never inside another corine and [2:32] never nested. The event loop is the [2:34] engine that schedules every corine call [2:37] back and timer. Asiosleep does not block [2:41] the thread. It tells the loop come back [2:43] to me later. This is the core mental [2:46] model. One loop, many co- routines, [2:49] cooperative pausing. Now let's run [2:51] multiple co- routines at the same time. [2:53] Look at the code on the left. Sequential [2:56] await. We await fetch of one, then fetch [2:59] of two, then fetch of three. Each takes [3:01] 1 second and a wait blocks until each [3:04] finishes before starting the next. Total [3:07] time about 3 seconds. On the right, [3:11] concurrent with Asencio. [3:13] We pass all three co- routines to [3:15] essentiate [3:18] the whole thing at once. All three start [3:21] immediately and run concurrently. Total [3:24] time about 1 second. The time of the [3:27] slowest task, not the sum. [3:29] Assentio.gather [3:31] returns the results as a list in in the [3:33] same order you pass the corines in, [3:36] regardless of which one finishes first. [3:38] This is the single biggest performance [3:40] win in async code. Independent IO [3:43] operations should almost always run with [3:46] gather not sequential await. Asio.create [3:50] task lets you start a co- routine [3:52] running in the background immediately [3:54] without waiting for it. Look at the [3:56] code. We define a worker function that [3:59] sleeps for a delay then prints done. [4:01] Inside main, we call essentio.create [4:04] task for worker A with a 2-cond delay. [4:08] and again for worker B with a 1second [4:10] delay. Both lines return immediately. [4:13] The tasks are scheduled but main keeps [4:15] running. We print both started right [4:18] away. Then we await T1 and await T2 to [4:21] collect their results. Even though A was [4:23] created first, B finishes first because [4:26] B's delay is shorter. The scheduling [4:29] order is not the completion order. [4:31] Create underscore task is how you fire [4:34] off work now and collect the result [4:36] later. Perfect for background jobs, [4:39] logging or fire and forget operations [4:41] you still want to track. Some resources [4:43] need asynchronous setup and cleanup [4:46] database connections, network sessions, [4:48] locks. That's what async with is for. [4:51] Look at the code. We define an async [4:54] connection class. Dunder enter is an [4:57] async method. It awaits connect_b [5:00] to open the connection and returns it. [5:03] Dunder exit is also async. It awaits the [5:06] connections close method to clean up [5:08] inside main async with async connection [5:11] open perin close pin as con gives us the [5:15] connection object. We await conexecute [5:18] inside the block when the block exits [5:21] even if an exception occurs. Dunder exit [5:23] runs automatically and the connection [5:26] closes. Async with is the asynchronous [5:28] version of the regular with statement. [5:31] same guarantee of cleanup, but every [5:33] step can be in non-blocking await. [5:35] You'll see this pattern in database [5:37] drivers, HTTP client sessions, and [5:41] distributed locks. Let's look at three [5:43] productionready async patterns. First, [5:46] timeouts with essentio.we_4. [5:49] Wrap any co- routine with a timeout in [5:52] seconds. If it doesn't finish in time, [5:55] essenti [5:56] error is raised. Catch it and return a [5:59] fall back. Second limiting concurrency [6:02] with essentio.seaphore. [6:04] Create a semaphore with a fixed limit. [6:06] Then async with sim before each [6:09] operation only that many operations run [6:12] at once. Everything else waits its turn. [6:14] This prevents overwhelming a server with [6:17] thousands of simultaneous requests. [6:19] Third, async iteration with async 4. An [6:23] async generator yields values one at a [6:25] time awaiting between each. Perfect for [6:28] streaming lines from a file or [6:30] pageionated API results. All three [6:33] patterns combine, a semaphore limited [6:35] timeout protected async generator is the [6:38] backbone of any serious data pipeline. [6:41] Asio ships with several essential tools. [6:44] Let's cover the four most important [6:46] ones. First, as Entios sleep, a [6:50] non-blocking pause. It yields control [6:52] back to the event loop instead of [6:54] freezing the thread. Second, [6:57] essentio.weight_4 [6:59] runs a co- routine with a timeout [7:02] raising timeout error if it's too slow. [7:04] Third essentio.task [7:07] group available in Python 311 and later. [7:10] Structured concurrency create tasks [7:13] inside the group and if any task raises [7:16] all other tasks are automatically [7:18] canled. Fourth, essentio.q an async safe [7:22] producer consumer queue. Producers [7:24] await, put, consumers await, get. These [7:27] four tools handle pausing, timeouts, [7:30] structure concurrency, and inter task [7:32] communication. Use them before reaching [7:35] for threads or third party async [7:37] libraries. Our mini project, a [7:40] concurrent API fetcher with a semaphore [7:42] rate limit. This is the pattern used in [7:45] every production data pipeline. Look at [7:47] the code. We define an async fetch [7:50] function that takes a session, a URL, [7:52] and a semaphore. Async with sim limits [7:56] how many requests run at once. Inside [7:59] async with session get awaits the [8:01] response and returns the JSON. Fetch_all [8:05] creates a semaphore with a given limit, [8:07] opens one a client session, builds a [8:10] list of fetch co- routines, one per URL, [8:13] and awaits a cinio. rather on all of [8:15] them at once. We call Asenio.run [8:19] with limit equals 10, meaning up to 10 [8:21] requests run concurrently. The rest Q [8:24] automatically. This single pattern can [8:26] fetch thousands of Earls, respect a [8:29] server's rate limits, and finish in a [8:31] fraction of the time sequential code [8:32] would take. Your challenge, build an [8:35] async pipeline from scratch. Step one, [8:38] write an async fetch user function that [8:41] takes an ID, awaits a centio. To [8:44] simulate network delay, and returns a [8:47] fake user dict. Step two, use [8:49] essentio.gather to fetch 10 users [8:52] concurrently and print the total elapse [8:54] time. Step three, wrap the gather call [8:57] with an essentio. [8:59] of three so only three fetches run at [9:02] once. Compare the timing. Step four, [9:05] write an async context manager called [9:07] timer that prints elapse time on exit [9:10] using dunder enter and dunder exit. Step [9:13] five, combine everything into one async [9:16] main function and run it with [9:17] essentio.run. Paste your full pipeline [9:20] and the timing output in the comments. I [9:23] read every single one. Let's recap what [9:25] you learned today. Async defaf defines a [9:28] co- routine. Calling it returns an [9:30] object it doesn't run yet. Await runs a [9:33] co- routine and pauses until the result [9:36] is ready, yielding control to the event [9:38] loop. Assentio.run is the entry point. [9:42] It creates runs and closes the event [9:44] loop call at once. Assencio.gather runs [9:48] many corines concurrently. Total time is [9:51] roughly the slowest one, not the sum. [9:54] Assentio.create [9:56] task schedules work immediately. Await [9:59] it later for the result. Async width, [10:02] dunder enter, and dunder exit handle [10:04] asynchronous setup and cleanup. Wait [10:07] underscore for ads timeouts and [10:09] semaphore limits concurrency. The mini [10:12] project built a concurrent API fetcher [10:14] with a rate limiting semaphore. Next [10:16] episode, context managers with dunder [10:19] enter, dunder exit, and context slip. [10:23] Subscribe so you don't miss it. See you [10:25] tomorrow. Async mastered. Your Python [10:28] code now runs concurrently without [10:31] blocking on a single IO call. Subscribe [10:33] for the next episode. Drop your async [10:36] pipeline in the comments. I am Aas. See [10:39] you in episode 26.