Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Asynchronous Programming with Asyncio
Mangabo Kolawole
Mangabo KolawoleSubscriber

Posted on

     

Asynchronous Programming with Asyncio

In the programming world, the concept of "non-blocking" is pervasive. JavaScript developers often use the term "asynchronous" because it is one of JavaScript's strengths. However, to truly understand asynchronous programming, it's essential to grasp the concepts of concurrent and parallel programming.

Concurrent Programming

When several independent entities are working simultaneously, the programming is concurrent. It doesn't necessarily mean that these tasks are running at the exact same time. Instead, it means that tasks are making progress over time by sharing resources, such as CPU time. The main advantage of concurrent programming is its robustness: if one process crashes, the rest of your program continues to function.

Parallel Programming

If an algorithm can divide its work into several parts, it is parallel. The more processors you have, the more you benefit from parallelism. Efficient parallel programming optimizes the resources of modern machines for better performance.

Illustrating Concurrency vs. Parallelism with Cooking

Concurrency Example:

Imagine you are preparing a meal where you need to grill some meat and make a sauce. You start by putting the meat on the barbecue. While the meat is grilling, you chop the tomatoes and other vegetables for the sauce. Then, you begin boiling the sauce while occasionally checking on the meat. Here, both tasks (grilling the meat and making the sauce) are in progress, but you are switching your attention between them. This represents concurrency.

Parallelism Example:

Now, let's say you have a friend to help you. While you focus on grilling the meat, your friend takes care of making the sauce. Both tasks are being done simultaneously without the need to switch attention between them. This represents parallelism.

What is Asynchronous Programming?

Asynchronous programming involves handling input/output (I/O) operations that occur outside your program, such as user input, printing to a terminal, reading from a socket, or writing to disk. The key characteristics of asynchronous I/O are:

  • The time taken by the operation is not CPU-dependent. Instead, it depends on factors like disk speed, network latency, and other external conditions.

  • The program cannot predict when the operation will end.

For services with significant I/O (like web servers, databases, and deployment scripts), optimizing these operations can greatly improve performance.

Let's see examples of blocking code and non-blocking code.

Example of Blocking and Non-blocking Code

Consider a simple program:

importtimedeftask():time.sleep(2)print("Hello")for_inrange(3):task()
Enter fullscreen modeExit fullscreen mode

In this synchronous program, each task waits for the previous one to finish, causing delays.

Now, let's look at an asynchronous version usingasyncio:

importasyncioasyncdeftask():awaitasyncio.sleep(2)print("Hello")asyncdefmain():tasks=[task()for_inrange(3)]awaitasyncio.gather(*tasks)asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

In this asynchronous program, tasks run concurrently, reducing the total execution time. Let's explore the components of asynchronous programming.

Components of Asynchronous Programming

Event loops, coroutines, and futures are the essential elements of an asynchronous Python program.

  • Event Loop: Manages task switching and execution flow, keeping track of tasks to be run asynchronously.

  • Coroutines: Special functions that can be paused and resumed, allowing other tasks to run during the wait. A coroutine specifies where in the function the task-switching event should take place, returning control to the event loop. Coroutines are typically created by the event loop and stored internally in a task queue.

  • Futures: Placeholders for results from coroutines, storing the result or exceptions. As soon as the event loop initiates a coroutine, a corresponding future is created that stores the result of the coroutine, or an exception if one was thrown during the coroutine’s execution.

With the crucial parts of asynchronous programming in Python explained, let's write some code.

Writing Asynchronous Code

Now that you understand the asynchronous programming pattern, let's write a little script and analyze the execution. Here’s a simple asynchronous script:

importasyncioasyncdeftask():awaitasyncio.sleep(2)print("Hello")asyncdefmain():tasks=[task()for_inrange(3)]awaitasyncio.gather(*tasks)asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

In the code above, we are trying to continue the execution of other tasks even if another one executing is sleeping (blocking). Notice theasync keyword in front of thetask andmain functions.

Those functions are nowcoroutines.

Coroutines functions in Python are preceded by the keywordasync. Themain() function here is the task coordinator or our single event loop, as it executes all tasks using theasync.gather method. Theasyncio.gather function runsawaitable objects concurrently.

Output:

HelloHelloHelloProgramexecutedin2.01seconds.
Enter fullscreen modeExit fullscreen mode

When each task reachesawait asyncio.sleep(2), it simply goes to the next task and comes back when it's finished. It's like saying, "I am going to sleep for 2 seconds. Do something else."

Let's see the synchronous version for a quick comparison.

importtimedeftask():time.sleep(2)print("Hello")for_inrange(3):task()
Enter fullscreen modeExit fullscreen mode

In the code above, we are going the traditional programming way in Python. You will notice that the execution of the process will take much more time.

Output:

HelloHelloHelloProgramexecutedin6.01seconds.
Enter fullscreen modeExit fullscreen mode

Now you can notice the execution time. Think oftime.sleep() as a blocking task andasyncio.sleep() as a non-blocking or long task. In asynchronous programming, the benefit of awaiting something, likeasyncio.sleep(), is that the surrounding function can temporarily cede control to another function that is ready to execute immediately.

With some basic examples of asynchronous programming in Python understood, let's explore the rules of asynchronous programming in Python.

Rules of Asyncio Programming

  1. Coroutines: Coroutines cannot be executed directly. If you try to run a coroutine function directly, it returns a coroutine object. Instead, useasyncio.run():

    importasyncioasyncdefhello():awaitasyncio.sleep(1)print('Hello')asyncio.run(hello())
  2. Awaitable Objects: Coroutines, futures, and tasks are the main awaitable objects. Python coroutines are awaitables and can be awaited from other coroutines.

  3. Await Keyword:await can only be used within async functions.

    asyncdefhello():awaitasyncio.sleep(1)print("Hello")
  4. Compatibility: Not all Python modules are compatible with asynchronous programming. For example, replacingawait asyncio.sleep() withtime.sleep() will cause an error. You can check the list of compatible and maintained moduleshere.

In the next section, we will explore a common use of asynchronous programming, HTTP requests.

Program Example: Asynchronous Requests

Let's take a look at the following piece of code:

importaiohttpimportasyncioasyncdeffetch(session,city):url=f"https://www.prevision-meteo.ch/services/json/{city}"asyncwithsession.get(url)asresponse:data=awaitresponse.json()print(f"Temperature at{city}:{data['current_condition']['tmp']} C")asyncdefmain():asyncwithaiohttp.ClientSession()assession:cities=['paris','toulouse','marseille']tasks=[fetch(session,city)forcityincities]awaitasyncio.gather(*tasks)asyncio.run(main())
Enter fullscreen modeExit fullscreen mode

In the code above, we create two asynchronous functions: one to fetch data from theprevision-meteo URL and amain function to execute the processes in the Python code. The goal is to send asynchronous HTTP GET requests to retrieve temperatures and print the responses.

In themain andfetch functions, we useasync with. In thefetch function,async with ensures that the connection is closed properly. In themain function, it ensures that theClientSession is closed after completing the requests. These practices are important in asynchronous coding in Python to manage resources efficiently and prevent leaks.

In the last line of themain function, we useawait asyncio.gather(*tasks). In our case, it runs all tasks concurrently, allowing the program to send multiple HTTP requests simultaneously. Usingawait ensures that the program waits for all tasks to complete before proceeding.

Output:

Temperatureatmarseille:25CTemperatureattoulouse:24CTemperatureatparis:18CProgramexecutedin5.86seconds.
Enter fullscreen modeExit fullscreen mode

Synchronous Version for Comparison

Code:

importrequestsimporttimedeffetch(city):url=f"https://www.prevision-meteo.ch/services/json/{city}"response=requests.get(url)data=response.json()print(f"Temperature at{city}:{data['current_condition']['tmp']} C")defmain():cities=['paris','toulouse','marseille']forcityincities:fetch(city)start_time=time.time()main()print(f"Program executed in{time.time()-start_time:.2f} seconds.")
Enter fullscreen modeExit fullscreen mode

Output:

TemperatureatParis:18CTemperatureatToulouse:24CTemperatureatMarseille:25CProgramexecutedin9.01seconds.
Enter fullscreen modeExit fullscreen mode

When to Use Asynchronous Programming

The asynchronous model performs best when:

  • There are a large number of tasks, ensuring at least one task can always progress.

  • Tasks involve significant I/O, causing an asynchronous program to waste lots of time blocking when other tasks could be running.

  • Tasks are largely independent, minimizing inter-task communication (and thus for one task to wait upon another).

Conclusion

In this tutorial, we covered:

  • The concepts of asynchronous programming and related concepts.

  • Effective use of async/await.

  • Making asynchronous HTTP requests with aiohttp.

  • The benefits of asynchronous programming.

Thanks for reading. The second part will cover asynchronous programming with Django.

Resources

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
mikekenneth77 profile image
Mike Houngbadji
Hi, just a problem solver, I use mainly Python. Working in Data Engineering & Analytics, though still connected to the web/apps dev community.
  • Location
    World
  • Joined

Well explained.

CollapseExpand
 
koladev profile image
Mangabo Kolawole
Software Engineer | Technical Writer | Book Author
  • Email
  • Location
    Remote
  • Education
    Studied CS
  • Work
    Software Engineer
  • Joined

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software Engineer | Technical Writer | Book Author
  • Location
    Remote
  • Education
    Studied CS
  • Work
    Software Engineer
  • Joined

More fromMangabo Kolawole

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp