Async in Python

Arpit Singh
3 min readMay 6, 2020

Who can wait quietly while the mud settles?
Who can remain still until the moment of action?

Laozi, Tao Te Ching

What is async in general?

You go to the doctor. You take the appointment. Either you wait in the queue idle or take out your laptop and start trading in the meantime (if you are a trader). The second options is an async way of doing things, where you don’t do things sequentially wherein u suffer with resource idleness and non-premptivness

Another analogy based explanation here -> link

Another example would be the way Vishwanathan Anand played chess against multiple players at the same time.

But python is single-threaded, how do we achieve async?

Async has nothing to do with multi-threading. In an async environment, a single process thread runs all the time, but it may, for event-driven reasons switch from one function to another.

Any drawbacks?

They might be some race conditions, since the order in which events are being handled is not under us. However they can be managed using low level apis.

  • The event loop design in node is the best example of asynchronous programming.

Lets understand few common terms in async programming in python.

  • Coroutine : A coroutine is a generalisation of a subroutine which allows cooperative multitasking by allowing programmers to take or give control from one coroutine to another. If a programmer is a cook, then boiling milk can be a coroutine where u can give away control and engage into something else, whereas making curd is a subroutine where u cannot skip or give away control
  • Event loop : An Event loop is a programming construct that listens to events before matching each event to a function that we have explicitly matched with said type of event. It helps register, execute and cancel calls, launch sub processes and associate transport for communication with external programs.
  • Await : Await passes the control back to the event loop telling to suspend suspend surrounding coroutines. Lets understand with an example.
async def g():
# Pause here and come back to g() when f() is ready
r = await f()
return r

When our python process encounters await f(), the event loop is notified to stop further execution of g() and wait till f() returns.

Writing our first async code in Python

Our hero - Asyncio

import asyncioasync def main():
print("hello")
await asyncio.sleep(1)
print("world")
asyncio.run(main())

Once asyncio.run(main()) is called

  • An event loop is created and starts listening for events
  • It will start the main function with loop.run_until_complete(main()) internally
  • When the function call reaches await, the main() coroutine will be suspended temporarily and a new coroutine asyncio.sleep() starts.
  • Transfers the control back to the main() after a second
  • The function exists, and the event loop is closed.

Note: If you try running asyncio.run(function) in Jupyter notebook, it will throw a Runtime exception. Rather just go ahead with await(function), reason being jupyter notebook internally starts an event loop upon bootstrapping.

Interesting topics to explore in this section would be Futures, Generator based coroutines, Asyncio Design Patterns, Queues etc.

Thank you for reading.

--

--