I recently needed to call some synchronous code from asyncio . Thankfully, asyncio provides the run_in_executor
function, which runs the specified function in a different thread. Here is an example of using it:
call_sync_code.py download
import asyncio
import time
from urllib.request import urlopen
@asyncio.coroutine
def count_to_10 ():
for i in range ( 11 ):
print ( "Counter: {}" . format ( i ))
yield from asyncio . sleep ( . 5 )
def get_page_len ( url ):
# This is the blocking sleep (not the async-friendly one)
time . sleep ( 2 )
page = urlopen ( url ) . read ()
return len ( page )
@asyncio.coroutine
def run_get_page_len ():
loop = asyncio . get_event_loop ()
future1 = loop . run_in_executor ( None , get_page_len , 'http://calebmadrigal.com' )
#data1 = yield from future1
return future1
@asyncio.coroutine
def print_data_size ():
data = yield from run_get_page_len ()
print ( "Data size: {}" . format ( data ))
loop = asyncio . get_event_loop ()
tasks = [
asyncio . async ( count_to_10 ()),
asyncio . async ( print_data_size ())]
loop . run_until_complete ( asyncio . wait ( tasks ))
loop . close ()
And here is the output:
Counter: 0
Counter: 1
Counter: 2
Counter: 3
Counter: 4
Counter: 5
Data size: 337581
Counter: 6
Counter: 7
Counter: 8
Counter: 9
Counter: 10
As you can see, even while the get_page_len()
blocking function is running, the count_to_10()
coroutine is still running as desired. Yay.