Asyncio blocking code

Asyncio is greats piece of software. But all Python code is not compatible. In the following example we will see how to run blocking code from your asyncio code.

We will by a simple asyncio application:

import asyncio
import time

@asyncio.coroutine
def clock():
    while True:
        print("Current time from asynchronous code: {}".format(int(time.time())))
        yield from asyncio.sleep(1)


def main():
    loop = asyncio.get_event_loop()
    asyncio.async(clock())
    loop.run_forever()

if __name__ == '__main__':
    main()

The output is:

Current time from asynchronous code: 1422265105
Current time from asynchronous code: 1422265106

And add blocking code:

import asyncio
import time

@asyncio.coroutine
def clock():
    while True:
        print("Current time from asynchronous code: {}".format(int(time.time())))
        yield from asyncio.sleep(1)

def blocking():
    while True:
        print("Current time from blocking code: {}".format(int(time.time())))
        time.sleep(1)

def main():
    loop = asyncio.get_event_loop()
    blocking()
    asyncio.async(clock())
    loop.run_forever()

if __name__ == '__main__':
    main()

The output is:

Current time from blocking code: 1422265410
Current time from blocking code: 1422265411
Current time from blocking code: 1422265412

If you want to run blocking code in your asynchronous code you need to run it in a different thread. Hopefully asyncio provide BaseEventLoop.run_in_executor where you can execute code in a different executor. You can pass None in order to execute your code in the default executor: ThreadPoolExecutor.

import asyncio
import time

@asyncio.coroutine
def clock():
    while True:
        print("Current time from asynchronous code: {}".format(int(time.time())))
        yield from asyncio.sleep(1)

def blocking():
    while True:
        print("Current time from blocking code: {}".format(int(time.time())))
        time.sleep(1)

def main():
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, blocking)
    asyncio.async(clock())
    loop.run_forever()

if __name__ == '__main__':
    main()

The output is:

Current time from blocking code: 1422265601
Current time from asynchronous code: 1422265601
Current time from blocking code: 1422265602
Current time from asynchronous code: 1422265602
Current time from blocking code: 1422265603

run_in_executor return a future and if an exception is raise your code is not stopped you need to check the future. A dummy sample code for stopping your code when something arrive:

import asyncio
import time
import concurrent

@asyncio.coroutine
def clock():
    while True:
        print("Current time from asynchronous code: {}".format(int(time.time())))
        yield from asyncio.sleep(1)

def blocking():
    while True:
        print("Current time from blocking code: {}".format(int(time.time())))
        time.sleep(1)
        raise Exception("Test")

def main():
    loop = asyncio.get_event_loop()
    block = loop.run_in_executor(None, blocking)
    async = asyncio.async(clock())
    loop.run_until_complete(asyncio.wait([block, async], return_when=concurrent.futures.FIRST_COMPLETED))
    print(block.exception())

if __name__ == '__main__':
    main()