HOW TO DEAL WITH
BLOCKING CODE WITHIN
ASYNCIO EVENT LOOP
Nikolay Novik
http://github.com/jettify
I AM ...
Software Engineer: at DataRobot Ukraine
Github:
My Projects:
database clients:
aiomysql, aioobc, aiogibson
web and etc:
aiohttp_debugtoolbar, aiobotocore,
aiohttp_mako, aiohttp_sse, aiogearman,
aiomysql_replicatoin
http://github.com/jettify
POLL
YOU AND ASYNCIO:
1. I am using asyncio extensively
2. I am using Twisted, Tornado, gevent etc. extensively
3. I think async programming is kinda cool
ASYNCIO
The asyncio project was officially launched with the release
of Python 3.4 in March 2014.
Bare: almost no library
One year later, asyncio has a strong community writing
libraries on top of it.
But what to do when available libraries work in sync way,
potentially blocking event loop?
RULES OF ASYNC CLUB
RULE #1
You do not block event loop
RULE #2
You never block event loop
BLOCKING CALLS IN THIRD PARTY
LIBRARIES
Network IO
API wrappers
Database clients
Message queues
FileSystem IO
CPU
Set environment variable
DEBUGGING BLOCKING CALLS TIP
PYTHONASYNCIODEBUG=1
import asyncio
import time
loop = asyncio.get_event_loop()
loop.slow_callback_duration = 0.01
async def sleeper():
time.sleep(0.1) # we block here
loop.run_until_complete(sleeper())
Executing <Task finished coro=<sleeper() done, defined at
code/debug_example.py:9> result=None created at
/usr/local/lib/python3.5/asyncio/base_events.py:323>
took 0.102 seconds
APPROACH #1 IS THERE ANY
SUITABLE LIBRARY?
Search asyncio compatible library on:
1. google ~ 98k results
2. pypi ~200 packages
3. asyncio wiki page:
4. aio-libs:
https://github.com/python/asyncio/wiki/ThirdParty
https://github.com/aio-libs
Read the (f*g) source code of your libraries! Example of
python code from OneDrive SDK
Most of the time you want to do HTTP requests using event
loop not thread pool.
THIRD PARTY LIBRARIES PRO TIP
@asyncio.coroutine
def get_async(self):
"""Sends the GET request using an asyncio coroutine
....
"""
future = self._client._loop.run_in_executor(None,
self.get)
collection_response = yield from future
return collection_response
Most hipsters databases use REST API as primary access
method:
Easy to implement required subset of APIs.
APPROACH #2 IS REST API AVAILABLE?
DynamoDB
Neo4j
Elasticsearch
HBase
HDFS
CouchDB
Riak
VoltDB
InfluxDB
ArangoDB
is your friend
Connection pooling helps to save on expensive connection
creation. (PS: checkout new aiohttp 0.18.x release)
REST CLIENT TIP
aiohttp.ClientSession
import asyncio
import aiohttp
# carry the loop Luke!
loop = asyncio.get_event_loop()
async def go():
session = aiohttp.ClientSession(loop=loop)
async with session.get('http://python.org') as resp:
data = await resp.text()
print(data)
session.close()
loop.run_until_complete(go())
APPROACH #3 IS THERE SIMPLE TEXT
OR BINARY PROTOCOL?
Example of databases and message queues with binary
protocol:
redis
memcached
couchebase
grearman
beanstalkd
disque
Do not afraid to get your hands dirty.
Example: Simple binary protocol implementation
Simple but no protocol pipelining.
import asyncio, struct
from aiogibson import encode_command
async def read_from_connection(host, port, *, loop=None):
reader, writer = await asyncio.open_connection(
host, port, loop=loop)
cmd = encode_command(b'GET', 'key')
writer.write(cmd)
header = await reader.readexactly(4 + 2 + 1)
unpacked = struct.unpack(b'<HBI', header)
code, gb_encoding, resp_size = unpacked
payload = await reader.readexactly(resp_size)
print(payload)
Most binary protocols support pipelining
More info: http://tailhook.github.io/request-pipelining-
presentation/ presentation/index.html
PROTOCOL PIPELINING
Example: Simple pipelined binary protocol implementation
See for reference implementation.
def execute(self):
cmd = encode_command(b'GET', 'key')
self.writer.write(cmd)
fut = asyncio.Future(loop=self._loop)
self._queue.append(fut)
return fut
async def reader_task(self):
while True:
header = await self.reader.readexactly(4 + 2 + 1)
unpacked = struct.unpack(b'<HBI', header)
code, gb_encoding, resp_size = unpacked
# wait and read payload
payload = await reader.readexactly(resp_size)
future = self._queue.pop()
future.set_result(payload)
aioredis
In good sync database clients IO decoupled from protocol
parsers why not just rewrite IO part?
APPROACH #4 IS SYNC PYTHON CLIENT
AVAILABLE?
1. Locate socket.recv()
2. Replace with await reader.read()
3. Make function coroutine with async def
4. Call this function with await
5. Call parent functions with await
Yes. Make every blocking call in separate thread
APPROACH #5 IS THERE UNIVERSAL
SOLUTION TO ALL PROBLEMS?
import asyncio
from pyodbc import connect
loop = asyncio.get_event_loop()
executor = ThreadPoolExecutor(max_workers=4)
async def test_example():
dsn = 'Driver=SQLite;Database=sqlite.db'
conn = await loop.run_in_executor(executor, connect, dsn)
cursor = await loop.run_in_executor(executor, conn.cursor)
conn = await loop.run_in_executor(executor, cursor.execute,
'SELECT 42;')
loop.run_until_complete(test_example())
For python code
For Cython
BUT HOW I KNOW WHICH METHOD TO
CALL IN THREAD?
requests.get()
with nogil:
[code to be executed with the GIL released]
For C extension
Py_BEGIN_ALLOW_THREADS
ret = SQLDriverConnect(hdbc, 0, szConnect, SQL_NTS,
0, 0, 0, SQL_DRIVER_NOPROMPT);
Py_END_ALLOW_THREADS
Only good way to use files asynchronously by using thread
pools.
WHAT ABOUT FILESYSTEM IO?
asyncio does not support asynchronous operations on the
filesystem due to OS limitations.
On background uses ThreadPoolExecutor for
blocking calls.
aiofiles library workaround
async def go():
f = await aiofiles.open('filename', mode='r')
try:
data = await f.read()
finally:
await f.close()
print(data)
loop.run_until_complete(go())
aiofiles
WHAT ABOUT CPU INTENSIVE TASK?
loop = asyncio.get_event_loop()
executor = ProcessPoolExecutor(max_workers=3)
def is_prime(n):
if n % 2 == 0: return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0: return False
return True
async def go():
n = 112272535095293
result = await loop.run_in_executor(executor, is_prime, n)
loop.run_until_complete(go(loop, executor))
THANKS!

More Related Content

DOCX
Heavy-Equipment-HSE-Checklists-hseprof-com.docx
PDF
HSE Management Plan
PPT
TREINAMENTO MANUSEIO de Químicos.ppt
PPTX
Basic liffting Rigging and Signalling.pptx
PPTX
Safety Talk K3.pptx
PPT
Security training module
PPTX
NR 35 Treinamento.pptx - Trabalho em Altura - Segurança
DOCX
Modelo de Plano de Ação de Emergência.docx.docx
Heavy-Equipment-HSE-Checklists-hseprof-com.docx
HSE Management Plan
TREINAMENTO MANUSEIO de Químicos.ppt
Basic liffting Rigging and Signalling.pptx
Safety Talk K3.pptx
Security training module
NR 35 Treinamento.pptx - Trabalho em Altura - Segurança
Modelo de Plano de Ação de Emergência.docx.docx

What's hot (20)

PPT
Industrial safetY of height works
PDF
F2630 2019 Editable Hot Work Permit.pdf
DOC
Height work permit
PPTX
Certificado_Modelo NR20_atualizado.17.04.17_Completo.pptx
PDF
Escritório Projetos Outsourcing de Data Center
PDF
3.-Confined-Space.pdf
PDF
Lifting rigging test
PDF
Programa de treinamento interno nr 18
DOC
Apr 005 --andaime_suspenso
PPT
HazCom_1.ppt
PPT
management of change
DOCX
Cv shahid hussain_hse manager
DOC
Apr 002 oficina de fabricação embutido
PPTX
Work_Permit_ijin kerja berbahaya PPT.pptx
PDF
Planejamento Mensal dos Diálogos Diários de Segurança - DDS
PPTX
General mining and underground induction
PPTX
HIRARC Training.pptx
PDF
Treinamento NR 12 - Ferramentas manuais.pdf
PDF
construction macheinery Safety.pdf
Industrial safetY of height works
F2630 2019 Editable Hot Work Permit.pdf
Height work permit
Certificado_Modelo NR20_atualizado.17.04.17_Completo.pptx
Escritório Projetos Outsourcing de Data Center
3.-Confined-Space.pdf
Lifting rigging test
Programa de treinamento interno nr 18
Apr 005 --andaime_suspenso
HazCom_1.ppt
management of change
Cv shahid hussain_hse manager
Apr 002 oficina de fabricação embutido
Work_Permit_ijin kerja berbahaya PPT.pptx
Planejamento Mensal dos Diálogos Diários de Segurança - DDS
General mining and underground induction
HIRARC Training.pptx
Treinamento NR 12 - Ferramentas manuais.pdf
construction macheinery Safety.pdf
Ad

Similar to HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP (20)

PDF
BUILDING APPS WITH ASYNCIO
PDF
Introduction to Python Asyncio
PDF
Original slides from Ryan Dahl's NodeJs intro talk
KEY
Plack perl superglue for web frameworks and servers
ODP
Building serverless application on the Apache Openwhisk platform
ODP
Lucio Grenzi - Building serverless applications on the Apache OpenWhisk platf...
PDF
Syncing up with Python’s asyncio for (micro) service development, Joir-dan Gumbs
KEY
node.js: Javascript's in your backend
PDF
Release with confidence
PDF
MongoDB World 2018: Tutorial - Got Dibs? Building a Real-Time Bidding App wit...
PPTX
Async programming and python
PDF
Logging for Production Systems in The Container Era
PDF
HTML5 tutorial: canvas, offfline & sockets
PPTX
PHP on Heroku: Deploying and Scaling Apps in the Cloud
PPTX
Node Session - 1
PDF
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
PPT
Exploring Node.jS
PDF
Why scala is not my ideal language and what I can do with this
PPTX
PPTX
Everything you wanted to know about writing async, concurrent http apps in java
BUILDING APPS WITH ASYNCIO
Introduction to Python Asyncio
Original slides from Ryan Dahl's NodeJs intro talk
Plack perl superglue for web frameworks and servers
Building serverless application on the Apache Openwhisk platform
Lucio Grenzi - Building serverless applications on the Apache OpenWhisk platf...
Syncing up with Python’s asyncio for (micro) service development, Joir-dan Gumbs
node.js: Javascript's in your backend
Release with confidence
MongoDB World 2018: Tutorial - Got Dibs? Building a Real-Time Bidding App wit...
Async programming and python
Logging for Production Systems in The Container Era
HTML5 tutorial: canvas, offfline & sockets
PHP on Heroku: Deploying and Scaling Apps in the Cloud
Node Session - 1
Adopt DevOps philosophy on your Symfony projects (Symfony Live 2011)
Exploring Node.jS
Why scala is not my ideal language and what I can do with this
Everything you wanted to know about writing async, concurrent http apps in java
Ad

Recently uploaded (20)

PPTX
"Secure File Sharing Solutions on AWS".pptx
PDF
Guide to Food Delivery App Development.pdf
PDF
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
PPTX
CNN LeNet5 Architecture: Neural Networks
PPTX
GSA Content Generator Crack (2025 Latest)
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PDF
Practical Indispensable Project Management Tips for Delivering Successful Exp...
PPTX
Download Adobe Photoshop Crack 2025 Free
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
E-Commerce Website Development Companyin india
PPTX
Tech Workshop Escape Room Tech Workshop
PPTX
Computer Software - Technology and Livelihood Education
PDF
How Tridens DevSecOps Ensures Compliance, Security, and Agility
PDF
Topaz Photo AI Crack New Download (Latest 2025)
PDF
Ableton Live Suite for MacOS Crack Full Download (Latest 2025)
DOC
UTEP毕业证学历认证,宾夕法尼亚克拉里恩大学毕业证未毕业
PDF
Salesforce Agentforce AI Implementation.pdf
PDF
MCP Security Tutorial - Beginner to Advanced
PDF
Microsoft Office 365 Crack Download Free
PDF
CCleaner 6.39.11548 Crack 2025 License Key
"Secure File Sharing Solutions on AWS".pptx
Guide to Food Delivery App Development.pdf
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
CNN LeNet5 Architecture: Neural Networks
GSA Content Generator Crack (2025 Latest)
DNT Brochure 2025 – ISV Solutions @ D365
Practical Indispensable Project Management Tips for Delivering Successful Exp...
Download Adobe Photoshop Crack 2025 Free
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
E-Commerce Website Development Companyin india
Tech Workshop Escape Room Tech Workshop
Computer Software - Technology and Livelihood Education
How Tridens DevSecOps Ensures Compliance, Security, and Agility
Topaz Photo AI Crack New Download (Latest 2025)
Ableton Live Suite for MacOS Crack Full Download (Latest 2025)
UTEP毕业证学历认证,宾夕法尼亚克拉里恩大学毕业证未毕业
Salesforce Agentforce AI Implementation.pdf
MCP Security Tutorial - Beginner to Advanced
Microsoft Office 365 Crack Download Free
CCleaner 6.39.11548 Crack 2025 License Key

HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP

  • 1. HOW TO DEAL WITH BLOCKING CODE WITHIN ASYNCIO EVENT LOOP Nikolay Novik http://github.com/jettify
  • 2. I AM ... Software Engineer: at DataRobot Ukraine Github: My Projects: database clients: aiomysql, aioobc, aiogibson web and etc: aiohttp_debugtoolbar, aiobotocore, aiohttp_mako, aiohttp_sse, aiogearman, aiomysql_replicatoin http://github.com/jettify
  • 3. POLL YOU AND ASYNCIO: 1. I am using asyncio extensively 2. I am using Twisted, Tornado, gevent etc. extensively 3. I think async programming is kinda cool
  • 4. ASYNCIO The asyncio project was officially launched with the release of Python 3.4 in March 2014. Bare: almost no library One year later, asyncio has a strong community writing libraries on top of it. But what to do when available libraries work in sync way, potentially blocking event loop?
  • 5. RULES OF ASYNC CLUB RULE #1 You do not block event loop RULE #2 You never block event loop
  • 6. BLOCKING CALLS IN THIRD PARTY LIBRARIES Network IO API wrappers Database clients Message queues FileSystem IO CPU
  • 7. Set environment variable DEBUGGING BLOCKING CALLS TIP PYTHONASYNCIODEBUG=1 import asyncio import time loop = asyncio.get_event_loop() loop.slow_callback_duration = 0.01 async def sleeper(): time.sleep(0.1) # we block here loop.run_until_complete(sleeper()) Executing <Task finished coro=<sleeper() done, defined at code/debug_example.py:9> result=None created at /usr/local/lib/python3.5/asyncio/base_events.py:323> took 0.102 seconds
  • 8. APPROACH #1 IS THERE ANY SUITABLE LIBRARY? Search asyncio compatible library on: 1. google ~ 98k results 2. pypi ~200 packages 3. asyncio wiki page: 4. aio-libs: https://github.com/python/asyncio/wiki/ThirdParty https://github.com/aio-libs
  • 9. Read the (f*g) source code of your libraries! Example of python code from OneDrive SDK Most of the time you want to do HTTP requests using event loop not thread pool. THIRD PARTY LIBRARIES PRO TIP @asyncio.coroutine def get_async(self): """Sends the GET request using an asyncio coroutine .... """ future = self._client._loop.run_in_executor(None, self.get) collection_response = yield from future return collection_response
  • 10. Most hipsters databases use REST API as primary access method: Easy to implement required subset of APIs. APPROACH #2 IS REST API AVAILABLE? DynamoDB Neo4j Elasticsearch HBase HDFS CouchDB Riak VoltDB InfluxDB ArangoDB
  • 11. is your friend Connection pooling helps to save on expensive connection creation. (PS: checkout new aiohttp 0.18.x release) REST CLIENT TIP aiohttp.ClientSession import asyncio import aiohttp # carry the loop Luke! loop = asyncio.get_event_loop() async def go(): session = aiohttp.ClientSession(loop=loop) async with session.get('http://python.org') as resp: data = await resp.text() print(data) session.close() loop.run_until_complete(go())
  • 12. APPROACH #3 IS THERE SIMPLE TEXT OR BINARY PROTOCOL? Example of databases and message queues with binary protocol: redis memcached couchebase grearman beanstalkd disque Do not afraid to get your hands dirty.
  • 13. Example: Simple binary protocol implementation Simple but no protocol pipelining. import asyncio, struct from aiogibson import encode_command async def read_from_connection(host, port, *, loop=None): reader, writer = await asyncio.open_connection( host, port, loop=loop) cmd = encode_command(b'GET', 'key') writer.write(cmd) header = await reader.readexactly(4 + 2 + 1) unpacked = struct.unpack(b'<HBI', header) code, gb_encoding, resp_size = unpacked payload = await reader.readexactly(resp_size) print(payload)
  • 14. Most binary protocols support pipelining More info: http://tailhook.github.io/request-pipelining- presentation/ presentation/index.html PROTOCOL PIPELINING
  • 15. Example: Simple pipelined binary protocol implementation See for reference implementation. def execute(self): cmd = encode_command(b'GET', 'key') self.writer.write(cmd) fut = asyncio.Future(loop=self._loop) self._queue.append(fut) return fut async def reader_task(self): while True: header = await self.reader.readexactly(4 + 2 + 1) unpacked = struct.unpack(b'<HBI', header) code, gb_encoding, resp_size = unpacked # wait and read payload payload = await reader.readexactly(resp_size) future = self._queue.pop() future.set_result(payload) aioredis
  • 16. In good sync database clients IO decoupled from protocol parsers why not just rewrite IO part? APPROACH #4 IS SYNC PYTHON CLIENT AVAILABLE? 1. Locate socket.recv() 2. Replace with await reader.read() 3. Make function coroutine with async def 4. Call this function with await 5. Call parent functions with await
  • 17. Yes. Make every blocking call in separate thread APPROACH #5 IS THERE UNIVERSAL SOLUTION TO ALL PROBLEMS? import asyncio from pyodbc import connect loop = asyncio.get_event_loop() executor = ThreadPoolExecutor(max_workers=4) async def test_example(): dsn = 'Driver=SQLite;Database=sqlite.db' conn = await loop.run_in_executor(executor, connect, dsn) cursor = await loop.run_in_executor(executor, conn.cursor) conn = await loop.run_in_executor(executor, cursor.execute, 'SELECT 42;') loop.run_until_complete(test_example())
  • 18. For python code For Cython BUT HOW I KNOW WHICH METHOD TO CALL IN THREAD? requests.get() with nogil: [code to be executed with the GIL released] For C extension Py_BEGIN_ALLOW_THREADS ret = SQLDriverConnect(hdbc, 0, szConnect, SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT); Py_END_ALLOW_THREADS
  • 19. Only good way to use files asynchronously by using thread pools. WHAT ABOUT FILESYSTEM IO? asyncio does not support asynchronous operations on the filesystem due to OS limitations.
  • 20. On background uses ThreadPoolExecutor for blocking calls. aiofiles library workaround async def go(): f = await aiofiles.open('filename', mode='r') try: data = await f.read() finally: await f.close() print(data) loop.run_until_complete(go()) aiofiles
  • 21. WHAT ABOUT CPU INTENSIVE TASK? loop = asyncio.get_event_loop() executor = ProcessPoolExecutor(max_workers=3) def is_prime(n): if n % 2 == 0: return False sqrt_n = int(math.floor(math.sqrt(n))) for i in range(3, sqrt_n + 1, 2): if n % i == 0: return False return True async def go(): n = 112272535095293 result = await loop.run_in_executor(executor, is_prime, n) loop.run_until_complete(go(loop, executor))