{"id":134930,"date":"2023-09-23T06:50:42","date_gmt":"2023-09-23T06:50:42","guid":{"rendered":"https:\/\/blog.finxter.com\/?p=1651739"},"modified":"2023-09-23T06:50:42","modified_gmt":"2023-09-23T06:50:42","slug":"python-async-io-the-ultimate-guide-in-a-single-post","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2023\/09\/23\/python-async-io-the-ultimate-guide-in-a-single-post\/","title":{"rendered":"Python Async IO \u2013 The Ultimate Guide in a Single Post"},"content":{"rendered":"\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-top\" data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;1651739&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;top&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;1&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;5&quot;,&quot;greet&quot;:&quot;Rate this post&quot;,&quot;legend&quot;:&quot;5\\\/5 - (1 vote)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Python Async IO - The Ultimate Guide in a Single Post&quot;,&quot;width&quot;:&quot;142.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n<div class=\"kksr-stars\">\n<div class=\"kksr-stars-inactive\">\n<div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div class=\"kksr-stars-active\" style=\"width: 142.5px;\">\n<div class=\"kksr-star\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<div class=\"kksr-star\" style=\"padding-right: 5px\">\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\"> 5\/5 &#8211; (1 vote) <\/div>\n<\/p><\/div>\n<p>As a Python developer, you might have come across the concept of asynchronous programming. Asynchronous programming, or async I\/O, is a concurrent programming design that has received dedicated support in Python, evolving rapidly from <a href=\"https:\/\/blog.finxter.com\/how-to-check-your-python-version\/\">Python 3.4 through 3.7<\/a> and beyond. With async I\/O, you can manage multiple tasks concurrently without the complexities of parallel programming, making it a perfect fit for I\/O bound and high-level structured network code.<\/p>\n<p>In the Python world, the <code><a href=\"https:\/\/blog.finxter.com\/how-to-check-asyncio-package-version-in-python\/\">asyncio<\/a><\/code> library is your go-to tool for implementing asynchronous I\/O. This library provides various <strong>high-level APIs to run Python coroutines concurrently, giving you full control over their execution<\/strong>. It also enables you to perform network I\/O, Inter-process Communication (IPC), control subprocesses, and synchronize concurrent code using tasks and queues.<\/p>\n<h2 class=\"wp-block-heading\">Understanding Asyncio<\/h2>\n<p>In the world of Python programming, <strong>asyncio<\/strong> plays a crucial role in designing efficient and concurrent code without using threads. It is a library that helps you manage tasks, event loops, and coroutines. To fully benefit from <code>asyncio<\/code>, you must understand some key components.<\/p>\n<p>First, let&#8217;s start with <strong>coroutines<\/strong>. They are special functions that can pause their execution at specified points without completely terminating it. In Python, you declare a coroutine using the <code>async def<\/code> syntax. <\/p>\n<p>For instance:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">async def my_coroutine(): # Your code here\n<\/pre>\n<p>Next, the <strong>event loop<\/strong> is a core feature of asyncio and is responsible for executing tasks concurrently and managing I\/O operations. An event loop runs tasks one after the other and can pause a task when it is waiting for external input, such as reading data from a file or from the network. It also listens for other tasks that are ready to run, switches to them, and resumes the initial task when it receives the input.<\/p>\n<p><strong>Tasks<\/strong> are the coroutines wrapped in an object, managed by the event loop. They are used to run multiple concurrent coroutines simultaneously. You can create a task using the <code>asyncio.create_task()<\/code> function, like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">async def my_coroutine(): # Your code here task = asyncio.create_task(my_coroutine())\n<\/pre>\n<p>Finally, the <code>sleep<\/code> function in asyncio is used to simulate I\/O bound tasks or a delay in the code execution. It works differently than the standard <code>time.sleep()<\/code> function as it is non-blocking and allows other coroutines to run while one is paused. You can use <code>await asyncio.sleep(delay)<\/code> to add a brief pause in your coroutine execution.<\/p>\n<p>Putting it all together, you can use <code>asyncio<\/code> to efficiently manage multiple coroutines concurrently:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def task_one(): print('Starting task one') await asyncio.sleep(3) print('Finished task one') async def task_two(): print('Starting task two') await asyncio.sleep(1) print('Finished task two') async def main(): task1 = asyncio.create_task(task_one()) task2 = asyncio.create_task(task_two()) await task1 await task2 # Run the event loop\nasyncio.run(main())\n<\/pre>\n<p>In this example, the event loop will start running both tasks concurrently, allowing task two to complete while task one is paused during the sleep period. This allows you to handle multiple tasks in a single-threaded environment. <\/p>\n<p>You can see it play out in this Gif:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" fetchpriority=\"high\" width=\"568\" height=\"598\" src=\"https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/asynch9999.gif\" alt=\"\" class=\"wp-image-1651747\"\/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\">Async\/Await Syntax<\/h2>\n<p>In Python, the <a href=\"https:\/\/blog.finxter.com\/python-async-await-mastering-concurrent-programming\/\">async\/await<\/a> syntax is a powerful tool to create and manage asynchronous tasks without getting lost in callback hell or making your code overly complex.<\/p>\n<p>The async\/await keywords are at the core of asynchronous code in Python. You can use the <code>async def<\/code> keyword to define an asynchronous function. Inside this function, you can use the <code>await<\/code> keyword to pause the execution of the function until some asynchronous operation is finished. <\/p>\n<p>For example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def main(): print(\"Start\") await asyncio.sleep(2) print(\"End\")\n<\/pre>\n<p><a href=\"https:\/\/blog.finxter.com\/python-async-generator-mastering-asyncio-in-modern-applications\/\"><code>yield<\/code> and <code>yield from<\/code><\/a> are related to asynchronous code in the context of generators, which provide a way to iterate through a collection of items without loading all of them into memory at once. In Python 3.3 and earlier, <code>yield from<\/code> was used to delegate a part of a generator&#8217;s operation to another generator. However, in later versions of Python, the focus shifted to async\/await for managing asynchronous tasks, and <code>yield from<\/code> became less commonly used.<\/p>\n<p>For example, before Python 3.4, you might have used a generator with <code>yield<\/code> and <code>yield from<\/code> like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def generator_a(): for i in range(3): yield i def generator_b(): yield from generator_a() for item in generator_b(): print(item)\n<\/pre>\n<p>With the introduction of async\/await, asynchronous tasks can be written more consistently and readably. You can convert the previous example to use async\/await as follows:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def async_generator_a(): for i in range(3): yield i await asyncio.sleep(1) async def async_generator_b(): async for item in async_generator_a(): print(item) await async_generator_b()\n<\/pre>\n<\/p>\n<h2 class=\"wp-block-heading\">Working with Tasks and Events<\/h2>\n<p>In asynchronous programming with Python, you&#8217;ll often work with tasks and events to manage the execution of simultaneous IO-bound operations. To get started with this model, you&#8217;ll need to understand the <strong>event loop<\/strong> and the concept of <strong>tasks<\/strong>.<\/p>\n<p>The event loop is a core component of Python&#8217;s <code>asyncio<\/code> module. It&#8217;s responsible for managing and scheduling the execution of tasks. A task, created using <code>asyncio.create_task()<\/code>, represents a coroutine that runs independently of other tasks in the same event loop.<\/p>\n<p>To create tasks, first, define an asynchronous function using the <code>async def<\/code> syntax. Then, you can use the <code><a href=\"https:\/\/blog.finxter.com\/python-async-await-mastering-concurrent-programming\/\">await<\/a><\/code> keyword to make non-blocking calls within this function. The <code>await<\/code> keyword allows the event loop to perform other tasks while waiting for an asynchronous operation to complete. <\/p>\n<p>Here&#8217;s an example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def my_async_function(): print(\"Task started\") await asyncio.sleep(2) print(\"Task finished\") event_loop = asyncio.get_event_loop()\ntask = event_loop.create_task(my_async_function())\nevent_loop.run_until_complete(task)\n<\/pre>\n<p>In this example, <code>my_async_function<\/code> is an asynchronous function, and <code>await asyncio.sleep(2)<\/code> represents an asynchronous operation. The <code>event_loop.create_task()<\/code> method wraps the coroutine into a task, allowing it to run concurrently within the event loop.<\/p>\n<p>To execute tasks and manage their output, you can use <code>asyncio.gather()<\/code>. This function receives a list of tasks and returns their outputs as a list in the same order they were provided. Here&#8217;s an example of how you can use <code>asyncio.gather()<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def async_task_1(): await asyncio.sleep(1) return \"Task 1 completed\" async def async_task_2(): await asyncio.sleep(2) return \"Task 2 completed\" async def main(): tasks = [async_task_1(), async_task_2()] results = await asyncio.gather(*tasks) print(results) asyncio.run(main())\n<\/pre>\n<p>In this example, <code>asyncio.gather()<\/code> awaits the completion of both tasks and then collects their output in a list, which is printed at the end.<\/p>\n<p>Working with tasks and events in Python&#8217;s asynchronous IO model helps improve the efficiency of your code when dealing with multiple IO operations, ensuring smoother and faster execution. Remember to use <code>asyncio.create_task()<\/code>, <code>await<\/code>, and <code>asyncio.gather()<\/code> when handling tasks within your event loop.<\/p>\n<h2 class=\"wp-block-heading\">Coroutines and Futures<\/h2>\n<p>In Python, async IO is powered by coroutines and futures. <strong>Coroutines<\/strong> are functions that can be paused and resumed at specific points, allowing other tasks to run concurrently. They are declared with the <code>async<\/code> keyword and used with <code>await<\/code>. <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-task.html\">Asyncio coroutines<\/a> are the preferred way to write asynchronous code in Python.<\/p>\n<p>On the other hand, <strong>futures<\/strong> represent the result of an asynchronous operation that hasn&#8217;t completed yet. They are primarily used for interoperability between callback-based code and the async\/await syntax. With asyncio, <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-future.html\">Future objects<\/a> should be created using <code>loop.create_future()<\/code>.<\/p>\n<p>To execute multiple coroutines concurrently, you can use the <a href=\"https:\/\/stackoverflow.com\/questions\/32054066\/how-to-run-multiple-coroutines-concurrently-using-asyncio\"><code>gather<\/code><\/a> function. <code>asyncio.gather()<\/code> is a high-level function that takes one or more awaitable objects (coroutines or futures) and schedules them to run concurrently. Here&#8217;s an example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def foo(): await asyncio.sleep(1) return \"Foo\" async def bar(): await asyncio.sleep(2) return \"Bar\" async def main(): results = await asyncio.gather(foo(), bar()) print(results) asyncio.run(main())\n<\/pre>\n<p>In this example, both <code>foo()<\/code> and <code>bar()<\/code> coroutines run concurrently, and the <code>gather()<\/code> function returns a list of their results.<\/p>\n<p>Error handling in asyncio is done through the <code>set_exception()<\/code> method. If a coroutine raises an exception, you can catch the exception and attach it to the associated future using <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-future.html#asyncio.Future.set_exception\"><code>future.set_exception()<\/code><\/a>. This allows other coroutines waiting for the same future to handle the exception gracefully.<\/p>\n<p>In summary, working with coroutines and futures helps you write efficient, asynchronous code in Python. Use coroutines along with the async\/await syntax for defining asynchronous tasks, and futures for interacting with low-level callback-based code. Utilize functions like <code>gather()<\/code> for running multiple coroutines concurrently, and handle errors effectively with <code>future.set_exception()<\/code>.<\/p>\n<h2 class=\"wp-block-heading\">Threading and Multiprocessing<\/h2>\n<p>In the world of Python, you have multiple options for concurrent execution and managing concurrency. Two popular approaches to achieve this are <strong>threading<\/strong> and <strong>multiprocessing<\/strong>.<\/p>\n<p><strong>Threading<\/strong> can be useful when you want to improve the performance of your program by efficiently utilizing your CPU&#8217;s time. It allows you to execute multiple threads in parallel within a single process. Threads share memory and resources, which makes them lightweight and more suitable for I\/O-bound tasks. However, because of the Global Interpreter Lock (GIL) in Python, only one thread can execute at a time, limiting the benefits of threading for CPU-bound tasks. You can explore the <code>threading<\/code> module for building multithreaded applications.<\/p>\n<p><strong>Multiprocessing<\/strong> overcomes the limitations of threading by using multiple processes working independently. Each process has its own Python interpreter, memory space, and resources, effectively bypassing the GIL. This approach is better for CPU-bound tasks, as it allows you to utilize multiple cores to achieve true parallelism. To work with multiprocessing, you can use Python&#8217;s <code>multiprocessing<\/code> module.<\/p>\n<p>While both threading and multiprocessing help manage concurrency, it is essential to choose the right approach based on your application&#8217;s requirements. Threading is more suitable when your tasks are I\/O-bound, and multiprocessing is advisable for CPU-bound tasks. When dealing with a mix of I\/O-bound and CPU-bound tasks, using a combination of the two might be beneficial.<\/p>\n<p>Async I\/O offers another approach for handling concurrency and might be a better fit in some situations. However, understanding threading and multiprocessing remains crucial to make informed decisions and efficiently handle concurrent execution in Python.<\/p>\n<h2 class=\"wp-block-heading\">Understanding Loops and Signals<\/h2>\n<p>In the world of Python async IO, working with loops and signals is an essential skill to grasp. As a developer, you must be familiar with these concepts to harness the power of asynchronous programming.<\/p>\n<p>Event loops are at the core of asynchronous programming in Python. They provide a foundation for scheduling and executing tasks concurrently. The <code>asyncio<\/code> library helps you create and manage these event loops. You can experiment with event loops using Python&#8217;s <code>asyncio<\/code> REPL, which can be started by running <code>python -m asyncio<\/code> in your command line.<\/p>\n<p>Signals, on the other hand, are a way for your program to receive notifications about certain events, like a user interrupting the execution of the program. A common use case for handling signals in asynchronous programming involves stopping the event loop gracefully when it receives a termination signal like <code>SIGINT<\/code> or <code>SIGTERM<\/code>.<\/p>\n<p>A useful method for running synchronous or blocking functions in an asynchronous context is the <code>loop.run_in_executor()<\/code> method. This allows you to offload the execution of such functions to a separate thread or process, preventing them from blocking the event loop. For example, if you have a CPU-bound operation that cannot be implemented using <code>asyncio<\/code>&#8216;s native coroutines, you can utilize <code>loop.run_in_executor()<\/code> to keep the event loop responsive.<\/p>\n<p>Here&#8217;s a simple outline of using loops and signals together in your asynchronous Python code:<\/p>\n<ol>\n<li>Create an event loop using <code>asyncio.get_event_loop()<\/code>.<\/li>\n<li>Register your signal handlers with the event loop, typically by using the <code>loop.add_signal_handler()<\/code> method.<\/li>\n<li>Schedule your asynchronous tasks and coroutines in the event loop.<\/li>\n<li>Run the event loop using <code>loop.run_forever()<\/code>, which will keep running until you interrupt it with a signal or a coroutine stops it explicitly.<\/li>\n<\/ol>\n<h2 class=\"wp-block-heading\">Managing I\/O Operations<\/h2>\n<p>When working with I\/O-bound tasks in Python, it&#8217;s essential to manage I\/O operations efficiently. Using <strong>asyncio<\/strong> can help you handle these tasks concurrently, resulting in more performant and scalable code.<\/p>\n<p>I\/O-bound tasks are operations where the primary bottleneck is fetching data from input\/output sources like files, network requests, or databases. To improve the performance of your I\/O-bound tasks, you can use asynchronous programming techniques. In Python, this often involves using the <strong>asyncio<\/strong> library and writing non-blocking code.<\/p>\n<p>Typically, you&#8217;d use blocking code for I\/O operations, which means waiting for the completion of an I\/O task before continuing with the rest of the code execution. This blocking behavior can lead to inefficient use of resources and poor performance, especially in larger programs with multiple I\/O-bound tasks.<\/p>\n<p>Non-blocking code, on the other hand, allows your program to continue executing other tasks while waiting for the I\/O operation to complete. This can significantly improve the efficiency and performance of your program. When using Python&#8217;s <strong>asyncio<\/strong> library, you write non-blocking code with <strong>coroutines<\/strong>.<\/p>\n<p>For I\/O-bound tasks involving file operations, you can use libraries like <strong>aiofiles<\/strong> to perform asynchronous file I\/O. Just like with asyncio, aiofiles provides an API to work with files using non-blocking code, improving the performance of your file-based tasks.<\/p>\n<p>When dealing with network I\/O, the <strong><code>asyncio<\/code><\/strong> library provides APIs to perform tasks such as asynchronous reading and writing operations for sockets and other resources. This enables you to manage multiple network connections concurrently, efficiently utilizing your system resources.<\/p>\n<p>In summary, when managing I\/O operations in Python:<\/p>\n<ul>\n<li>Identify I\/O-bound tasks in your program<\/li>\n<li>Utilize the <strong>asyncio<\/strong> library to write non-blocking code using coroutines<\/li>\n<li>Consider using <strong>aiofiles<\/strong> for asynchronous file I\/O<\/li>\n<li>Utilize asyncio APIs to manage network I\/O efficiently<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Handling Transports and Timeouts<\/h2>\n<p>When working with Python&#8217;s Async IO, you might need to handle transports and timeouts effectively. Transports and protocols are low-level event loop APIs for implementing network or IPC protocols such as HTTP. They help improve the performance of your application by using callback-based programming style. You can find more details in the <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-protocol.html\">Python 3.11.4 documentation<\/a>.<\/p>\n<p>Timeouts are often useful when you want to prevent your application from waiting indefinitely for a task to complete. To handle timeouts in asyncio, you can use the <code>asyncio.wait_for<\/code> function. This allows you to set a maximum time that your function can run. If the function doesn&#8217;t complete within the specified time, an <code>asyncio.TimeoutError<\/code> is raised.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def some_function(): await asyncio.sleep(5) async def main(): try: await asyncio.wait_for(some_function(), timeout=3) except asyncio.TimeoutError: print(\"Task took too long.\") asyncio.run(main())\n<\/pre>\n<p>In this example, <code>some_function<\/code> takes 5 seconds to complete, but we set a timeout of 3 seconds. As a result, an <code>asyncio.TimeoutError<\/code> is raised, and the program prints &#8220;Task took too long.&#8221;<\/p>\n<p class=\"has-global-color-8-background-color has-background\">Another concept to be familiar with is the executor, which allows you to run synchronous functions in an asynchronous context. You can use the <code>loop.run_in_executor()<\/code> method, where <code>loop<\/code> is an instance of the event loop. This method takes three arguments: the executor, the function you want to run, and any arguments for that function. The executor can be a custom one or <code>None<\/code> for the default <code>ThreadPoolExecutor<\/code>. <\/p>\n<p>Here&#8217;s an example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio\nimport time def sync_function(seconds): time.sleep(seconds) return \"Slept for {} seconds\".format(seconds) async def main(): loop = asyncio.get_event_loop() result = await loop.run_in_executor(None, sync_function, 3) print(result) asyncio.run(main())\n<\/pre>\n<p>In this example, we run the synchronous <code>sync_function<\/code> inside the async <code>main()<\/code> function using the <code>loop.run_in_executor()<\/code> method.<\/p>\n<\/p>\n<h2 class=\"wp-block-heading\">Dealing with Logging and Debugging<\/h2>\n<p>When working with Python&#8217;s <code>asyncio<\/code> library, properly handling logging and debugging is essential for ensuring efficient and smooth development. As a developer, it&#8217;s crucial to stay confident and knowledgeable when dealing with these tasks.<\/p>\n<p>To begin logging in your asynchronous Python code, you need to initialize a logger object. Import the <code>logging<\/code> module and create an instance of the <code>Logger<\/code> class, like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import logging logger = logging.getLogger(__name__)\nlogger.setLevel(logging.DEBUG)\n<\/pre>\n<p>This configuration sets up a logger object that will capture debug-level log messages. To log a message, simply call the appropriate method like <code>logger.debug<\/code>, <code>logger.info<\/code>, or <code>logger.error<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">async def my_async_function(): logger.debug(\"Debug message\") logger.info(\"Info message\") logger.error(\"Error message\") await some_async_operation()\n<\/pre>\n<p>Keep in mind that Python&#8217;s logging module is not inherently asynchronous. However, there are ways to work around this issue. One approach is to use a <a href=\"https:\/\/stackoverflow.com\/questions\/45842926\/python-asynchronous-logging\"><code>ThreadPoolExecutor<\/code><\/a>, which executes logging methods in a separate thread:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import concurrent.futures\nimport logging executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) def log_info(msg, *args): executor.submit(logging.info, msg, *args) async def my_async_function(): log_info(\"Info message\") await some_async_operation()\n<\/pre>\n<p>For debugging your asynchronous code, it&#8217;s possible to enable the debug mode in asyncio by calling the <code>loop.set_debug()<\/code> method. Additionally, consider setting the log level of the <code>asyncio<\/code> logger to <code>logging.DEBUG<\/code> and configuring the <code>warnings<\/code> module to display <code>ResourceWarning<\/code> warnings. Check the <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-dev.html\">official Python documentation<\/a> for more information and best practices.<\/p>\n<\/p>\n<h2 class=\"wp-block-heading\">Understanding Virtual Environments and Resources<\/h2>\n<p>When working with Python, you&#8217;ll often encounter the need for a <strong>virtual environment<\/strong>. A virtual environment is an isolated environment for your Python applications, which allows you to manage resources and dependencies efficiently. It helps ensure that different projects on your computer do not interfere with each other in terms of dependencies and versions, maintaining the availability of the required resources for each project.<\/p>\n<p>To create a virtual environment, you can use built-in Python libraries such as <code>venv<\/code> or third-party tools like <code>conda<\/code>. Once created, you&#8217;ll activate the virtual environment and install the necessary packages needed for your project. This ensures that the resources are available for your application without causing conflicts with other Python packages or applications on your computer. <\/p>\n<p class=\"has-base-2-background-color has-background\"><img decoding=\"async\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/72x72\/1f517.png\" alt=\"\ud83d\udd17\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\" \/> For a more detailed explanation of virtual environments, check out this <a href=\"https:\/\/www.dataquest.io\/blog\/a-complete-guide-to-python-virtual-environments\/\">complete guide to Python virtual environments<\/a>.<\/p>\n<p>When working with async IO in Python, it&#8217;s crucial to manage resources effectively, especially when dealing with asynchronous operations like networking requests or file I\/O. By using a virtual environment, you can make sure that your project has the correct version of <code>asyncio<\/code> and other async libraries, ensuring that your code runs smoothly and efficiently.<\/p>\n<p>In a virtual environment, resources are allocated based, on the packages and libraries you install. This way, only the necessary resources for your project are used, improving performance and consistency across development. The virtual environment lets you keep track of your project&#8217;s dependencies, making it easier to maintain and share your project with others, ensuring that they can access the required resources without compatibility issues.<\/p>\n<\/p>\n<h2 class=\"wp-block-heading\">Optimizing Asynchronous Program<\/h2>\n<p>When working with Python, you may often encounter situations where an asynchronous program can significantly improve the performance and responsiveness of your application. This is especially true when dealing with I\/O-bound tasks or high-level structured network code, where <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio.html\"><code>asyncio<\/code><\/a> can be your go-to library for writing concurrent code.<\/p>\n<p>Before diving into optimization techniques, it&#8217;s crucial to understand the difference between synchronous and asynchronous programs. In a synchronous program, tasks are executed sequentially, blocking other tasks from running. Conversely, an asynchronous program allows you to perform multiple tasks concurrently without waiting for one to complete before starting another. This cooperative multitasking approach enables your asynchronous program to run much faster and more efficiently.<\/p>\n<p>To make the most of your asynchronous program, consider applying the following techniques:<\/p>\n<ol>\n<li><strong>Use async\/await syntax<\/strong>: Employing the <code>async<\/code> and <code>await<\/code> keywords when defining asynchronous functions and awaiting their results ensures proper execution and responsiveness.<\/li>\n<li><strong>Implement an event loop<\/strong>: The event loop is the core of an asyncio-based application. It schedules, executes, and manages tasks within the program, so it&#8217;s crucial to utilize one effectively.<\/li>\n<li><strong>Leverage libraries<\/strong>: Many asynchronous frameworks, such as web servers and database connection libraries, have been built on top of asyncio. Take advantage of these libraries to simplify and optimize your asynchronous program.<\/li>\n<li><strong>Avoid blocking code<\/strong>: Blocking code can slow down the execution of your asynchronous program. Ensure your program is entirely non-blocking by avoiding time-consuming operations or synchronous APIs.<\/li>\n<\/ol>\n<p>It&#8217;s essential to remember that while asynchronous programming has its advantages, it might not always be the best solution. In situations where your tasks are CPU-bound or require a more straightforward processing flow, a synchronous program might be more suitable.<\/p>\n<h2 class=\"wp-block-heading\">Exploring Asyncio Libraries and APIs<\/h2>\n<p>When working with asynchronous programming in Python, it&#8217;s essential to explore the available libraries you can use. One such library is <strong>aiohttp<\/strong>. It allows you to make asynchronous HTTP requests efficiently using <code>asyncio<\/code>. You can find more details about this library from the <a href=\"https:\/\/aiohttp.readthedocs.io\/en\/stable\/\"><code>aiohttp<\/code> documentation<\/a>.<\/p>\n<p>To get started with <code>aiohttp<\/code>, you&#8217;ll first need to install the library:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">pip install aiohttp\n<\/pre>\n<p>In your Python code, you can now import <code>aiohttp<\/code> and use it with the <code>asyncio<\/code> library. For example, if you want to make an asynchronous GET request, you can use the following code:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import aiohttp\nimport asyncio async def fetch_data(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text() async def main(): url = 'https:\/\/api.example.com\/data' data = await fetch_data(url) print(data) await main()\n<\/pre>\n<p>In the example above, the <code>fetch_data<\/code> function is defined as an async function using the <code>async def<\/code> syntax. This indicates that this function can be called with the <code>await<\/code> statement within other asynchronous functions.<\/p>\n<p>The <code>pathlib<\/code> library provides classes for working with filesystem paths. While it is not directly related to async IO, it can be useful when working with file paths in your async projects. The <code>pathlib.Path<\/code> class offers a more Pythonic way to handle file system paths, making it easier to manipulate file and directory paths across different operating systems. You can read more about this library in the <a href=\"https:\/\/docs.python.org\/3\/library\/pathlib.html\">official Python documentation on <code>pathlib<\/code><\/a>.<\/p>\n<p>When you create <a href=\"https:\/\/blog.finxter.com\/python-async-function\/\">async function<\/a> calls in your code, remember to use the <code>await<\/code> keyword when calling them. This ensures that the function is executed asynchronously. By combining the power of <code>aiohttp<\/code>, <code>asyncio<\/code>, and other async-compatible libraries, you can efficiently perform multiple tasks concurrently in your Python projects.<\/p>\n<\/p>\n<h2 class=\"wp-block-heading\">Understanding Queues and Terminals<\/h2>\n<p>With Python&#8217;s <code>asyncio<\/code> module, you can write concurrent, asynchronous code that works efficiently on I\/O-bound tasks and network connections. In this context, <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio-queue.html\">queues<\/a> become helpful tools for coordinating the execution of multiple tasks and managing shared resources.<\/p>\n<p>Queues in <code>asyncio<\/code> are similar to standard Python queues, but they have special asynchronous properties. With coroutine functions such as <code>get()<\/code> and <code>put()<\/code>, you can efficiently retrieve an item from the queue or insert an item, respectively. When the queue is empty, the <code>get()<\/code> function will wait until an item becomes available. This enables smooth flow control and ensures that your async tasks are executed in the most optimal order.<\/p>\n<p>Terminals, on the other hand, are interfaces for interacting with your system &#8211; either through command-line or graphical user interfaces. When working with async tasks in Python, terminals play a crucial role in tracking the progress and execution of your tasks. You can use terminals to initiate and monitor the state of your async tasks by entering commands and viewing the output.<\/p>\n<p>When it comes to incorporating multithreaded or asynchronous programming in a parent-child relationship, queues and terminals can come in handy. Consider a scenario where a parent task is responsible for launching multiple child tasks that operate concurrently. In this case, a queue can facilitate the communication and synchronization between parent and child tasks by efficiently passing data to and fro.<\/p>\n<p>Here are a few tips to keep in mind while working with queues and terminals in asynchronous Python programming:<\/p>\n<ul>\n<li>Use <code>asyncio.Queue()<\/code> to create an instance suitable for async tasks, while still maintaining similar functionality as a standard Python queue.<\/li>\n<li>For managing timeouts, remember to use the <code>asyncio.wait_for()<\/code> function in conjunction with queue operations, since the methods of <code>asyncio<\/code> queues don&#8217;t have a built-in timeout parameter.<\/li>\n<li>When working with terminals, be mindful of potential concurrency issues. Make sure you avoid race conditions by properly synchronizing your async tasks&#8217; execution using queues, locks, and other synchronization primitives provided by the <code>asyncio<\/code> module.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n<h3 class=\"wp-block-heading\">How does asyncio compare to threading in Python?<\/h3>\n<p>Asyncio is a concurrency model that uses a single thread and an event loop to execute tasks concurrently. While threading allows for concurrent execution of tasks using multiple threads, asyncio provides better performance by managing tasks in a non-blocking manner within a single thread. Thus, asyncio is often preferred when dealing with I\/O-bound tasks, as it can handle many tasks without creating additional threads.<\/p>\n<h3 class=\"wp-block-heading\">What are the main components of the asyncio event loop?<\/h3>\n<p>The asyncio event loop is responsible for managing asynchronous tasks in Python. Its main components include:<\/p>\n<ol>\n<li>Scheduling tasks: The event loop receives and schedules coroutine functions for execution.<\/li>\n<li>Managing I\/O operations: The event loop monitors I\/O operations and receives notifications when the operations are complete.<\/li>\n<li>Executing asynchronous tasks: The event loop executes scheduled tasks in a non-blocking manner, allowing other tasks to run concurrently.<\/li>\n<\/ol>\n<h3 class=\"wp-block-heading\">How do I use asyncio with pip?<\/h3>\n<p>To use asyncio in your Python projects, no additional installation is needed, as it is included in the Python Standard Library from Python version 3.4 onwards. Simply import asyncio in your Python code and make use of its features.<\/p>\n<h3 class=\"wp-block-heading\">What is the difference between asyncio.run() and run_until_complete()?<\/h3>\n<p><code>asyncio.run()<\/code> is a newer and more convenient function for running an asynchronous coroutine until it completes. It creates an event loop, runs the passed coroutine, and closes the event loop when the task is finished. <code>run_until_complete()<\/code> is an older method that requires an existing event loop object on which to run a coroutine.<\/p>\n<p>Here&#8217;s an example of how to use <code>asyncio.run()<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def example_coroutine(): await asyncio.sleep(1) print(\"Coroutine has completed\") asyncio.run(example_coroutine())\n<\/pre>\n<h3 class=\"wp-block-heading\">How can I resolve the &#8216;asyncio.run() cannot be called from a running event loop&#8217; error?<\/h3>\n<p>This error occurs when you try to call <code>asyncio.run()<\/code> inside an already running event loop. Instead of using <code>asyncio.run()<\/code> in this case, you should use <code>create_task()<\/code> or <code>gather()<\/code> functions to schedule your coroutines to run concurrently within the existing loop.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def example_coroutine(): await asyncio.sleep(1) print(\"Coroutine has completed\") async def main(): task = asyncio.create_task(example_coroutine()) await task asyncio.run(main())\n<\/pre>\n<h3 class=\"wp-block-heading\">Can you provide an example of using async\/await in Python?<\/h3>\n<p>Here&#8217;s a simple example demonstrating the use of async\/await in Python:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import asyncio async def async_function(): print(\"Function starting\") await asyncio.sleep(2) print(\"Function completed\") async def main(): await asyncio.gather(async_function(), async_function()) asyncio.run(main())\n<\/pre>\n<p>This example demonstrates two async functions running concurrently. The <code>main()<\/code> function uses <code>asyncio.gather()<\/code> to run both <code>async_function()<\/code> tasks at the same time, and <code>asyncio.run(main())<\/code> starts the event loop to execute them.<\/p>\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.finxter.com\/how-to-request-openais-api-asynchronously-in-python\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"572\" src=\"https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/image-102-1-1024x572.png\" alt=\"\" class=\"wp-image-1651742\" srcset=\"https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/image-102-1-1024x572.png 1024w, https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/image-102-1-300x168.png 300w, https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/image-102-1-768x429.png 768w, https:\/\/blog.finxter.com\/wp-content\/uploads\/2023\/09\/image-102-1.png 1254w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<p class=\"has-base-2-background-color has-background\"><img decoding=\"async\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/72x72\/26a1.png\" alt=\"\u26a1\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\" \/> <strong>Recommended<\/strong>: <a href=\"https:\/\/blog.finxter.com\/how-to-request-openais-api-asynchronously-in-python\/\">Can I Run OpenAI\u2019s API in Parallel? Yes, with Python Async!<\/a><\/p>\n<p>The post <a rel=\"nofollow\" href=\"https:\/\/blog.finxter.com\/python-async-io-the-ultimate-guide-in-a-single-post\/\">Python Async IO &#8211; The Ultimate Guide in a Single Post<\/a> appeared first on <a rel=\"nofollow\" href=\"https:\/\/blog.finxter.com\">Be on the Right Side of Change<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>5\/5 &#8211; (1 vote) As a Python developer, you might have come across the concept of asynchronous programming. Asynchronous programming, or async I\/O, is a concurrent programming design that has received dedicated support in Python, evolving rapidly from Python 3.4 through 3.7 and beyond. With async I\/O, you can manage multiple tasks concurrently without the [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[857],"tags":[73,468,528],"class_list":["post-134930","post","type-post","status-publish","format-standard","hentry","category-python-tut","tag-programming","tag-python","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/134930","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=134930"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/134930\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=134930"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=134930"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=134930"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}