AN INTRODUCTIONTO
PYTHON ASYNCIO
NathanVan Gheem

@vangheezy
nathanvangheem.com
Lead Platform Engineer @ Onna
ABOUT ME
Plone core contributor, framework, ui, sec teams,

Developer of Guillotina,

Lead Platform Engineer @ Onna
ASYNCIO,A DEFINITION
“This module provides infrastructure for writing
single-threaded concurrent code using coroutines,
multiplexing I/O access over sockets and other
resources, running network clients and servers, and
other related primitives” - https://docs.python.org/3/library/asyncio.html
ASYNC - IO
Asynchronous programming using async/await syntax
I/O with aTCP socket
WHAT DOES IT LOOK LIKE?
SO WHAT?
Web applications useTCP sockets
A way to improve performance and scale web
applications
Also think micro services
BENEFITS
The event loop allows you to handle a larger
number of network connections at once.
BENEFITS
Code does not block on network activity, so you can
have long running connections with very little
performance impact(HTML5 sockets for example)
REQUIREMENTS
Python >= 3.4
best features and performance in 3.6
HOWTYPICAL WEB SERVERS
ARE DESIGNED
• Pyramid
• Flask
• Django
• Plone
• Etc..
User Request(Web Browser)
Web Application
Use Available PythonThread
Render Request
Send Response to User(Web Browser)
Start over
SERVING REQUESTS(LEGACY)
Threads X Processes
=
Number of simultaneous requests
THREADED MODEL

AND WEB SOCKETS
Not practical

Can not keep threads open
THREADS AND PYTHON
Threads are expensive(GIL, context switching, CPU),

Processes are expensive on RAM
WEB SERVERTHREADING
MODEL…
If no threads available because they are busy, 

further requests are blocked,

waiting for an open thread
NETWORKTRAFFIC IS USED
EVERYWHERE
NETWORKTRAFFIC
(BROWSER/SERVER)
NETWORKTRAFFIC
(WEB APPLICATION/DATABASE)
NETWORKTRAFFIC
(WEB APPLICATION/CACHING)
NETWORKTRAFFIC
(WEB APPLICATION/AUTH)
NETWORKTRAFFIC

(WEB APPLICATION/CLOUD)
ASYNCIO SERVERS
Block on CPU(obviously)
ASYNCIO SERVERS
Can accept many simultaneous connections
ASYNCIO SERVERS
No blocking on network traffic
“reactive”
ASYNCIO SERVERS
Server
Requests

from user
AsyncIOTask

Request objects
ASYNCIO DEMONSTRATION
CPU ISTHE LIMIT
Limit CPU intensive operations

Scale with more processes,

or with connected micro-services(network traffic)
DETAILS…
In order to benefit,

the whole stack needs to be AsyncIO aware
NO - ASYNC - IO
Anywhere in your application server that is not
AsyncIO and does network traffic WILL BLOCK all
other connections while it is doing it’s network
traffic(example: using requests library instead of
aiohttp)
GETTING STARTED
1. Get active event loop or create
new one
2. Run coroutine inside event loop
with asyncio.run_until_complete
GETTING STARTED(CODE)
(basic.py)
AND WE HAVE FUTURES…
asyncio.run_until_complete automatically wraps your
coroutine into a Future object and waits for it to finish
asyncio.ensure_future will wrap a coroutine in a future
and return it to you
So you can schedule multiple coroutines that can run
at the same time
BASIC CONTINUED(CODE)
(basic2.py)
TASKS
You can also schedule long running tasks on the
event loop
Tasks are like futures
Tasks are futures, but pluggable on the event loop
with different implementations
LONG RUNNING
TASKS(CODE)
(basic3.py)
TASKS/FUTURES/COROUTINES
Well, it’s a bit odd we have distinctions
Consider all of these synonyms until you dive deeper
GOTCHA: EVERYTHING MUST
BE ASYNC
If you want part of your code to be async, the
complete stack of the caller must be async and
running on the event loop
ONCEYOU’RE ASYNC,

YOU’RE GOOD
You can also consider asyncio.run_until_complete as
a sort of bootstrap function
ASYNC EVERYTHING(CODE)
(async-everything.py)
SINGLETHREADED
Only 1 event loop can run in a thread at a time
Running multi-threaded code with AsyncIO code
running in a thread loop is unsafe
You can multi-(process|thread) and run multiple
threads at the same time
(multi-loop.py)
“MULTI” PROCESSING IN
ASYNCIO
asyncio.gather allows you to run multiple coroutines
at the same time, waiting for all of them to finish
There are also async context managers
MULTI PROCESS WITH
GATHER
(gather.py)
LOOPS
We can also utilize asyncio in for loops + yield
ASYNC LOOP(CODE)
(yield.py)
SCHEDULING
loop.call_later: arrange to call function on a delay
loop.call_at: arrange function to be called at specified
time
SCHEDULING(CODE)
(schedule.py)
EXECUTORS
An executor is available to use when you have non-async
code that needs to be made async, or CPU intensive code
A typical executor is a thread executor.This means, anything
you run in an executor is being thrown in a thread to run.
Try to avoid but it’s a tool available
It’s worse to have non-async code than to use thread
executors
EXECUTORS(CODE)
(exec.py)
ASYNC SUBPROCESS
The Python AsyncIO library comes with an amazing
subprocess module
SUBPROCESS
(subp).py)
EVENT LOOP IS PLUGGABLE
ALTERNATIVE

LOOP IMPLEMENTATIONS
• uvloop
• tokio(rust)
• Curio
AWESOME AIO
• aiohttp: client and server library
• aioes: elastic search
• asyncpg: postgresql
• aioredis
• aiobotocore
• aiosmtpd: smtp
• and many more. Check out https://github.com/aio-libs
DEBUGGING
• Debugging is more difficult than regular sequential programs
• pdb(debugger) statements do not properly skip over await
calls(because thread loop causes debugging to pay attention to
another call stack)
• pdb also causes thread loop to halt right there, there is no way to
manually execute task in loop in a pdb prompt either
• Making matters more annoying, python prompt doesn’t work with
asyncio
DEBUGGINGTOOLS
• aioconsole: allows you to have a python prompt
with asyncio loop already setup for you. So you
can run await statements! Guillotina runs it’s shell
command in an aioconsole.
• aiomonitor: attach to already running event loop
and get info on running tasks.Also integrated with
guillotina(run `g -m`)
GUILLOTINA!
guillotina: full web application built with asyncio
technologies. Lots of great examples
PYTHON 3.7
Execution context: like thread locals but for
coroutines(right now with aiotask-context)
QUESTIONTIME

Introduction to Python Asyncio