Professional Documents
Culture Documents
Asyncio Interview Questions
Asyncio Interview Questions
Jason Brownlee
2022
i
i
ii
Copyright
© Copyright 2022 Jason Brownlee. All Rights Reserved.
Disclaimer
The information contained within this book is strictly for educational purposes. If you wish
to apply ideas contained in this book, you are taking full responsibility for your actions.
The author has made every effort to ensure the accuracy of the information within this
book was correct at time of publication. The author does not assume and hereby disclaims
any liability to any party for any loss, damage, or disruption caused by errors or omissions,
whether such errors or omissions result from accident, negligence, or any other cause.
No part of this book may be reproduced or transmitted in any form or by any means, electronic
or mechanical, recording or by any information storage and retrieval system, without written
permission from the author.
ii
iii
Preface
Python concurrency is deeply misunderstood.
Opinions vary from “Python does not support concurrency” to “Python concurrency is buggy”.
I created the website SuperFastPython.com to directly counter these misunderstandings.
Python asyncio can be tricky and confusing for beginners.
I was once asked: How would you evaluate whether a developer understands Python concur-
rency?
This book is my answer to the question for Python asyncio, including the asyncio module
and coroutines.
For a Python developer to be effective, they must know how to use the API, and more
importantly, when to use it.
This book was carefully crafted to provide a long series of questions I might ask in an interview
to check if a developer really understands Python asyncio and how to bring coroutines and
asynchronous programming to a project.
My hope is that together, we can make Python code run faster and change the community’s
opinions about Python concurrency.
Thank you for letting me guide you along this path.
Jason Brownlee, Ph.D.
SuperFastPython.com
2022.
iii
Contents
Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ii
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
Introduction 1
Who Is This Book For? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Book Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
How to Read . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Which Python Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Getting Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Asynchronous Programming 4
Q. What does asynchronous mean? . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Q. What is an asynchronous function call? . . . . . . . . . . . . . . . . . . . . . . 4
Q. What is asynchronous programming? . . . . . . . . . . . . . . . . . . . . . . . 4
Q. What are two ways we can run asynchronous tasks with threads? . . . . . . . . 5
Q. What are two ways we can run asynchronous tasks with processes? . . . . . . . 5
Q. What is another programming language where asynchronous I/O is popular? . 6
Q. What are 3 benefits of using asynchronous programming? . . . . . . . . . . . . 6
Q. What area is asynchronous programming most useful and why? . . . . . . . . . 6
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Coroutines 7
Q. What are coroutines? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Q. What type of multitasking is achieved using coroutines? . . . . . . . . . . . . . 7
Q. What was the precursor to coroutines in Python? . . . . . . . . . . . . . . . . 7
Q. How are coroutines different from threads? . . . . . . . . . . . . . . . . . . . . 8
Q. What does the async/await syntax mean? . . . . . . . . . . . . . . . . . . . . 8
Q. What 3 async expressions were added to Python? . . . . . . . . . . . . . . . . 8
Q. What does the await expression do? . . . . . . . . . . . . . . . . . . . . . . . 8
Q. How do you define a coroutine? . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Q. What is a coroutine function? . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Q. What does a coroutine function return? . . . . . . . . . . . . . . . . . . . . . . 9
Q. How is a coroutine suspended? . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Q. What executes and switches between coroutines? . . . . . . . . . . . . . . . . . 10
Q. How are coroutines and subroutines similar and different? . . . . . . . . . . . . 10
iv
Contents v
Asyncio 12
Q. What is the asyncio module? . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Q. What does asyncio stand for? . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Q. What are the two APIs in asyncio and when should each be used? . . . . . . . 12
Q. What is blocking I/O? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Q. What is non-blocking I/O? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Q. What types of non-blocking I/O does asyncio offer? . . . . . . . . . . . . . . . 13
Q. What are 3 reasons to use asyncio? . . . . . . . . . . . . . . . . . . . . . . . . 13
Q. Is asyncio affected by the GIL? . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Q. What are 5 applications where we could use asyncio for non-blocking I/O? . . 14
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Run Coroutines 15
Q. How do you start an asyncio program? . . . . . . . . . . . . . . . . . . . . . . 15
Q. How do you run a single coroutine from a coroutine? . . . . . . . . . . . . . . . 15
Q. What is an awaitable? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Q. What are 3 examples of awaitables? . . . . . . . . . . . . . . . . . . . . . . . . 16
Q. How can you sleep asynchronously in a coroutine? . . . . . . . . . . . . . . . . 16
Q. Why would we sleep for zero seconds in a coroutine? . . . . . . . . . . . . . . . 16
Q. Can two or more coroutines run at the same time in the same event loop? . . . 16
Q. What suspends and resumes coroutines? . . . . . . . . . . . . . . . . . . . . . 17
Q. How do we return a value from a coroutine? . . . . . . . . . . . . . . . . . . . 17
Q. What happens if we don’t execute a coroutine? . . . . . . . . . . . . . . . . . . 17
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Tasks 18
Q. What is an asyncio future? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Q. What is an asyncio task? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Q. How do you create a task? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Q. How can we get all running tasks? . . . . . . . . . . . . . . . . . . . . . . . . . 19
Q. How can we get the currently running task? . . . . . . . . . . . . . . . . . . . 19
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
v
Contents vi
Blocking Tasks 33
Q. What is a blocking function? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Q. What happens if a coroutine calls a blocking function? . . . . . . . . . . . . . 33
Q. How we treat a blocking function like its non-blocking in asyncio? . . . . . . . 33
Q. How do we call blocking I/O-bound functions from asyncio? . . . . . . . . . . 34
Q. How do we call blocking CPU-bound functions from asyncio? . . . . . . . . . . 34
vi
Contents vii
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Event Loop 36
Q. What is the asyncio event loop? . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Q. How do we get the event loop object? . . . . . . . . . . . . . . . . . . . . . . . 36
Q. How do we exit the event loop? . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Q. How can another thread schedule a coroutine in an event loop? . . . . . . . . . 37
Q. How are coroutines represented in the event loop? . . . . . . . . . . . . . . . . 37
Q. Is the event loop multithreaded? . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Advanced Tasks 39
Q. How could we get a task by its name? . . . . . . . . . . . . . . . . . . . . . . . 39
Q. How could we wait for all background tasks? . . . . . . . . . . . . . . . . . . . 39
Q. How can we run a coroutine after a delay? . . . . . . . . . . . . . . . . . . . . 40
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Synchronization Primitives 49
Q. What does coroutine-safe mean? . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Q. Can we get race conditions with coroutines? . . . . . . . . . . . . . . . . . . . 49
Q. Can we get deadlocks with coroutines? . . . . . . . . . . . . . . . . . . . . . . 50
Q. How can we use a mutex to protect a critical section from coroutines? . . . . . 51
Q. How can a coroutine check if a mutex is locked? . . . . . . . . . . . . . . . . . 52
Q. When might we use an Event? . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Q. How can we check if an Event is set? . . . . . . . . . . . . . . . . . . . . . . . 52
Q. How can a coroutine set an Event? . . . . . . . . . . . . . . . . . . . . . . . . 53
Q. What is an asyncio condition variable? . . . . . . . . . . . . . . . . . . . . . . 53
Q. How can we wait to be notified with an asyncio condition variable? . . . . . . 53
Q. How can we notify all coroutines waiting on a condition? . . . . . . . . . . . . 54
vii
Contents viii
Q. What is a semaphore? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Q. How can we configure a semaphore? . . . . . . . . . . . . . . . . . . . . . . . . 55
Q. How can we use a semaphore to limit access to a critical section? . . . . . . . . 55
Q. How can we use a semaphore like a mutex? . . . . . . . . . . . . . . . . . . . . 56
Q. What happens if a coroutine tries to acquire a semaphore that has no space? . 56
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Queues 57
Q. Why would we use queues in an asyncio program? . . . . . . . . . . . . . . . . 57
Q. What 3 types of queues does asyncio provide? . . . . . . . . . . . . . . . . . . 57
Q. How can we define a fixed-sized queue? . . . . . . . . . . . . . . . . . . . . . . 57
Q. How do we add and remove items from a queue? . . . . . . . . . . . . . . . . . 58
Q. What happens if a coroutine adds an item to a queue that is full? . . . . . . . 58
Q. Why would we use the task_done() and join() methods? . . . . . . . . . . . 58
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Subprocesses 60
Q. How is running a command directly vs via the shell different? . . . . . . . . . . 60
Q. What are some common shells on Unix-based operating systems? . . . . . . . . 60
Q. How can we run a command directly from asyncio? . . . . . . . . . . . . . . . 60
Q. How can we run a command using the shell from asyncio? . . . . . . . . . . . . 61
Q. How do we interact with the subprocess running the command? . . . . . . . . 61
Q. Does the subprocess continue running if the asyncio event loop exits? . . . . . 61
Q. How can we read data from a subprocess? . . . . . . . . . . . . . . . . . . . . 61
Q. How can we write data to a subprocess? . . . . . . . . . . . . . . . . . . . . . . 62
Q. How can we stop a command running in a subprocess? . . . . . . . . . . . . . 62
Q. How can we wait for a subprocess to finish? . . . . . . . . . . . . . . . . . . . . 62
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Streams 64
Q. What are 5 common application-layer protocols used on the internet? . . . . . 64
Q. What are 3 socket programs you could develop involving a web server? . . . . 64
Q. How can we open a TCP client connection? . . . . . . . . . . . . . . . . . . . . 64
Q. How can we open a TCP server connection? . . . . . . . . . . . . . . . . . . . 65
Q. How would we connect to a web server on port 80? . . . . . . . . . . . . . . . 65
Q. How would we connect to a web server running HTTPS on the regular port? . 66
Q. What are two ways to read lines from a StreamReader? . . . . . . . . . . . . . 66
Q. How can we write lines of data to a StreamWriter? . . . . . . . . . . . . . . . 66
Q. What is the drain() method and when would we use it? . . . . . . . . . . . . 67
Q. How do we close a connection? . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Conclusions 69
Well Done! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Resources For Diving Deeper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
viii
Contents ix
ix
Introduction
Book Overview
This book provides a large number of questions on what, how and when to use the Python
asyncio API.
The questions are divided into major topics, they are:
• Asynchronous Programming
• Coroutines
• Asyncio
• Run Coroutines
• Run Coroutines
1
Introduction 2
How to Read
If you are a Python developer looking to learn asyncio, I recommend working through the
book sequentially from start-to-finish. You can pick and choose topics if you need to brush
up in specific areas.
If you are a Python developer looking to test your knowledge, I would recommend working
through questions one at a time. All questions are listed in the table of contents, which you
can use to test your knowledge. Record your answers, then compare your answers to the
answers provided later in the book.
If you are an engineering manager, I recommend selecting a sample of questions from the
book to ask in a technical interview. Perhaps select some general knowledge questions as
well as some questions that require a code listing that could be prepared on paper, a google
doc or whiteboard. The questions in the book may also be combined, remixed, or used to
inspire your own questions.
2
Introduction 3
Getting Help
The questions and answers are intentionally terse.
This is not a jump-start guide or master class. Instead, these are interview questions that
may be used for self-study or to test engineering capabilities.
Nevertheless, sometimes we need a little extra help.
A list of further reading resources is provided at the end of each section. These can be helpful
if you are interested in learning more about the topic covered, such as fine grained details of
the standard library and API functions used.
Finally, if you ever have questions about the interview questions or answers in this book, you
can contact me any time and I will do my best to help. My contact details are provided at
the end of the book.
Now that we know what’s coming, let’s get started.
Next
Next is the first topic where we will take a closer look at asynchronous programming.
3
Asynchronous Programming
4
Asynchronous Programming 5
The ThreadPoolExecutor provides the submit() method for issuing asynchronous tasks and
returning a Future that provides a handle on the task.
For example:
...
# issue an async function call
future = executor.submit(target_func)
The ProcessPoolExecutor provides the submit() method for issuing asynchronous tasks
and returning a Future that provides a handle on the task.
For example:
...
# issue an async function call
future = executor.submit(target_func)
5
Asynchronous Programming 6
Further Reading
This section provides additional resources on or related to this topic.
• Asynchrony (computer programming), Wikipedia.
https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)
• Asynchronous I/O, Wikipedia.
https://en.wikipedia.org/wiki/Asynchronous_I/O
• PEP 3156 – Asynchronous IO Support Rebooted: the asyncio Module.
https://peps.python.org/pep-3156/
• concurrent.futures - Launching parallel tasks.
https://docs.python.org/3/library/concurrent.futures.html
6
Coroutines
7
Coroutines 8
8
Coroutines 9
9
Coroutines 10
10
Coroutines 11
A coroutine can suspend or yield to another coroutine using an await expression. It will
then resume from this point once the awaited coroutine has been completed.
We might think of a generator as a special type of coroutine and cooperative multitasking
used in loops.
Further Reading
This section provides additional resources on or related to this topic.
• Coroutine, Wikipedia.
https://en.wikipedia.org/wiki/Coroutine
• Async/await, Wikipedia.
https://en.wikipedia.org/wiki/Async/await
• PEP 492 – Coroutines with async and await syntax.
https://peps.python.org/pep-0492/
• PEP 3156 – Asynchronous IO Support Rebooted: the asyncio Module.
https://peps.python.org/pep-3156/
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
11
Asyncio
12
Asyncio 13
A blocking read would involve requesting data and waiting for the data to arrive before
resuming the application.
It is called blocking because the execution of the program (e.g. thread or coroutine) cannot
proceed until the call returns.
13
Asyncio 14
Further Reading
This section provides additional resources on or related to this topic.
• I/O bound, Wikipedia.
https://en.wikipedia.org/wiki/I/O_bound
• Asynchronous I/O, Wikipedia.
https://en.wikipedia.org/wiki/Asynchronous_I/O
• PEP 3156 – Asynchronous IO Support Rebooted: the asyncio Module.
https://peps.python.org/pep-3156/
• Python Global Interpreter Lock, Python Wiki.
https://wiki.python.org/moin/GlobalInterpreterLock
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
14
Run Coroutines
A coroutine can also schedule a coroutine to run independently via the asyncio.create_task()
function.
For example:
...
# execute the coroutine independently
task = asyncio.create_task(other_coro())
15
Run Coroutines 16
Q. What is an awaitable?
An awaitable refers to a Python object that can be awaited via the await expression.
Technically, it is an object that implements the __await__() magic method.
16
Run Coroutines 17
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
17
Tasks
18
Tasks 19
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
• Asyncio Futures.
https://docs.python.org/3/library/asyncio-future.html
19
Working with Tasks
20
Working with Tasks 21
21
Working with Tasks 22
...
# add a done callback function
task.add_done_callback(handler)
22
Working with Tasks 23
23
Working with Tasks 24
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
24
Run Multiple Coroutines
This section covers questions regarding the running of many coroutines and tasks concurrently.
A large part of asyncio programs is often dedicated to running many tasks concurrently,
therefore, it is essential that we know how.
Let’s get started.
25
Run Multiple Coroutines 26
The result of asyncio.gather() is an iterable of return values from all awaitables passed as
an argument.
For example:
...
# get future for group of coroutines
future = asyncio.gather(coro1(), coro2(), coro3())
# execute the future
await future
# get the iterable of return values
values = future.result()
26
Run Multiple Coroutines 27
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
27
Working with Coroutines
28
Working with Coroutines 29
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
29
Waiting for Tasks
30
Waiting for Tasks 31
31
Waiting for Tasks 32
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
32
Blocking Tasks
This section covers questions related to executing blocking calls from asyncio programs.
There are many blocking calls we may need to complete within an asyncio program, such
as working with files, executing CPU-bound tasks, and working with legacy APIs. It is
important to know how to correctly handle blocking calls in asyncio.
Let’s get started.
33
Blocking Tasks 34
For example:
...
# execute a blocking call asynchronously in asyncio
await asyncio.to_thread(task)
Further Reading
This section provides additional resources on or related to this topic.
34
Blocking Tasks 35
35
Event Loop
The asyncio.get_event_loop() can also be used and will create an event loop if no loop is
running.
...
# get the event loop
loop = asyncio.get_event_loop()
36
Event Loop 37
37
Event Loop 38
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Asyncio Event Loop.
https://docs.python.org/3/library/asyncio-eventloop.html
38
Advanced Tasks
39
Advanced Tasks 40
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Coroutines and Tasks.
https://docs.python.org/3/library/asyncio-task.html
40
Iterators, Generators, and Context
Managers
This section covers questions on asynchronous iterators, asynchronous generators, and asyn-
chronous context managers.
These are an often overlooked area of asynchronous programming in Python, but critical to
application developers.
Let’s get started.
This does not execute the for-loop in parallel. The asyncio event loop is unable to execute
more than one coroutine at a time within a Python thread.
41
Iterators, Generators, and Context Managers 42
42
Iterators, Generators, and Context Managers 43
We can then create an instance of the asynchronous iterator and traverse it using an async
for expression.
The complete example is listed below.
# SuperFastPython.com
# example of using an asynchronous iterator
import asyncio
# main coroutine
async def main():
# loop over async iterator with async for loop
async for item in AsyncIterator():
print(item)
43
Iterators, Generators, and Context Managers 44
44
Iterators, Generators, and Context Managers 45
# main coroutine
async def main():
# loop over async generator with async for loop
async for item in async_generator():
print(item)
45
Iterators, Generators, and Context Managers 46
For example:
...
# await list comprehension
results = [await a for a in awaitables]
The current coroutine will be suspended to execute awaitables sequentially, which is different
and perhaps slower than executing them concurrently using asyncio.gather().
46
Iterators, Generators, and Context Managers 47
await asyncio.sleep(0.5)
# start
47
Iterators, Generators, and Context Managers 48
asyncio.run(custom_coroutine())
Further Reading
This section provides additional resources on or related to this topic.
• PEP 492 – Coroutines with async and await syntax.
https://peps.python.org/pep-0492/
• PEP 3156 – Asynchronous IO Support Rebooted: the asyncio Module.
https://peps.python.org/pep-3156/
• PEP 525 – Asynchronous Generators.
https://peps.python.org/pep-0525/
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
48
Synchronization Primitives
49
Synchronization Primitives 50
# main coroutine
async def main():
# get the current task
task1 = asyncio.current_task()
# create and execute the first task
task2 = asyncio.create_task(task(task1))
# execute the task, which will await task2
await task(task2)
50
Synchronization Primitives 51
asyncio.run(main())
51
Synchronization Primitives 52
# ...
# lock is released automatically...
We can also use an asyncio.Event to stop tasks that are running concurrently.
For example, each task may check the status of the event each iteration of their task and if
the event is set, they can return, effectively stopping the task.
For example:
...
# check if the event is set
if event.is_set():
# stop processing
return
52
Synchronization Primitives 53
...
# check if the event is set
if event.is_set():
# do something...
53
Synchronization Primitives 54
For example, we can acquire the condition variable, do something, then release the condition
as follows:
...
# acquire the condition
await condition.acquire()
# do something
# ...
# release the condition
condition.release()
An alternative to calling the acquire() and release() methods directly is to use the async
context manager, which will perform the acquire/release automatically for us, for example:
...
# acquire the condition
async with condition:
# do something
# ...
54
Synchronization Primitives 55
Q. What is a semaphore?
A semaphore is a concurrency primitive that allows a limit on the number of coroutines that
can acquire a lock protecting a critical section.
It is an extension of a mutual exclusion (mutex) lock that adds a count for the number of
coroutines that can acquire the lock before additional coroutines will block. Once full, new
coroutines can only acquire a position on the semaphore once an existing coroutine holding
the semaphore releases a position.
Internally, the semaphore maintains a counter protected by a mutex lock that is decremented
each time the semaphore is acquired and incremented each time it is released.
When a semaphore is created, the upper limit on the counter is set. If it is set to 1, then the
semaphore will operate like a mutex lock.
This can also be achieved using the asynchronous context manager interface and the async
with expression.
55
Synchronization Primitives 56
For example:
...
# acquire the semaphore
async with semaphore:
# critical section
# ...
Using this semaphore will only allow a single coroutine access to a critical section at a time,
just like a mutex lock.
Further Reading
This section provides additional resources on or related to this topic.
• Thread safety, Wikipedia.
https://en.wikipedia.org/wiki/Thread_safety
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Asyncio Synchronization Primitives.
https://docs.python.org/3/library/asyncio-sync.html
56
Queues
57
Queues 58
We can put an item on the queue without waiting via the put_nowait() method.
We can remove an item from the queue using the get() method.
This is a coroutine method and must be awaited. If the queue does not have any items
available, the caller will be suspended until an item becomes available.
For example:
...
# get an item from the queue
item = await queue.get()
58
Queues 59
A coroutine can wait for all items on the queue to be processed (at the time of the call) via
the join() method, which must be awaited.
This may be done by a coroutine that puts items on the queue and needs to know when all
those items have been consumed and handled by other coroutines.
For example:
...
# wait for all items to be processed
await queue.join()
Further Reading
This section provides additional resources on or related to this topic.
• Queue (abstract data type), Wikipedia.
https://en.wikipedia.org/wiki/Queue_(abstract_data_type)
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
• Asyncio Queues.
https://docs.python.org/3/library/asyncio-queue.html
59
Subprocesses
60
Subprocesses 61
...
# execute a command directly
process = await create_subprocess_exec('ls', '-l')
61
Subprocesses 62
...
# read byte data from the subprocess
byte_data = await process.communicate()
Further Reading
This section provides additional resources on or related to this topic.
• asyncio – Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
62
Subprocesses 63
• Asyncio Subprocesses.
https://docs.python.org/3/library/asyncio-subprocess.html
63
Streams
64
Streams 65
This is a coroutine function that must be awaited and returns a tuple containing a
StreamReader and StreamWriter for reading and writing from and to the connection.
For example:
...
# open a tcp socket connection
reader, writer = open_connection('www.google.com', 80)
...
# start a tcp server
start_server(client_handler, '127.0.0.1', 7890)
65
Streams 66
Alternatively, we can read lines of byte data one at a time using the async for expression
on the StreamReader directly.
For example:
...
# read lines of byte data
async for line_bytes in reader:
# ...
66
Streams 67
Alternatively, we can enumerate strings, encode each as byte data and call the write()
method for each.
For example:
...
# write string lines
for line in lines:
# encode as byte data
line_bytes = line.encode()
# write line byte data
writer.write(line_bytes)
Further Reading
This section provides additional resources on or related to this topic.
• Computer network programming, Wikipedia.
https://en.wikipedia.org/wiki/Computer_network_programming
• Application layer, Wikipedia.
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
67
Streams 68
68
Conclusions
Well Done!
Congratulations, you made it to the end of the book.
You have challenged your self with pointed interview questions.
You know how to use Python asyncio and bring coroutine-based concurrency and asynchronous
programming to your project.
Thank you for letting me help you on your journey into Python concurrency.
Jason Brownlee, Ph.D.
SuperFastPython.com
2022.
APIs
• Concurrent Execution API - Python Standard Library.
https://docs.python.org/3/library/concurrency.html
• multiprocessing API - Process-based parallelism.
https://docs.python.org/3/library/multiprocessing.html
• threading API - Thread-based parallelism.
https://docs.python.org/3/library/threading.html
• concurrent.futures API - Launching parallel tasks.
https://docs.python.org/3/library/concurrent.futures.html
• asyncio API - Asynchronous I/O.
https://docs.python.org/3/library/asyncio.html
Books
• High Performance Python, Ian Ozsvald, et al., 2020.
https://amzn.to/3wRD5MX
69
Conclusions 70
70
About the Author
Jason Brownlee, Ph.D. helps Python developers bring modern concurrency methods to their
projects with hands-on tutorials. Learn more at SuperFastPython.com.
Jason is a software engineer and research scientist with a background in artificial intelligence
and high-performance computing. He has authored more than 20 technical books on machine
learning and has built, operated, and exited online businesses.
71
Interview Questions Series
72