1

I want to test how asyncio handle blocking processes.

There must be something wrong with my code because asyncio.TimeoutError is never raised:

import asyncio, random, time

q = asyncio.Queue()

MAX_WAIT = 5

@asyncio.coroutine
def blocking_task(sec):
    print('This task will sleep {} sec.'.format(sec))
    time.sleep(sec)

@asyncio.coroutine
def produce():
    while True:
        q.put_nowait(random.randint(1,10))
        yield from asyncio.sleep(0.5 + random.random())

@asyncio.coroutine
def consume():
    while True:
        value = yield from q.get()
        try:
            yield from asyncio.wait_for(blocking_task(value), MAX_WAIT)
        except asyncio.TimeoutError:
            print('~/~ Job has been canceled !!')
        else:
            print('=/= Job has been done :]')


loop = asyncio.get_event_loop()
asyncio.ensure_future(produce())
asyncio.ensure_future(consume())
loop.run_forever()

This code produce the following output:

$ ./tst3.py 
This task will sleep 2 sec.
=/= Job has been done :]
This task will sleep 1 sec.
=/= Job has been done :]
This task will sleep 7 sec.
=/= Job has been done :]
NarūnasK
  • 4,564
  • 8
  • 50
  • 76

1 Answers1

2

Use asyncio.sleep instead of sleep

The TimeoutError of asyncio is different from buildin TimeoutError. That's why you can not use time.sleep to trigger this error. For triggering TimeoutError in asyncio.coroutine, you only can use timer which is implemented by asyncio module.

@asyncio.coroutine
def blocking_task(sec):
    print('This task will sleep {} sec.'.format(sec))
    yield from asyncio.sleep(sec)

Result

This task will sleep 10 sec.
~/~ Job has been canceled !!
This task will sleep 3 sec.
=/= Job has been done :]
This task will sleep 4 sec.
=/= Job has been done :]
This task will sleep 2 sec.
=/= Job has been done :]
This task will sleep 7 sec.
~/~ Job has been canceled !!
This task will sleep 2 sec.
=/= Job has been done :]
Kir Chou
  • 2,980
  • 1
  • 36
  • 48
  • What if there was other long running blocking function (not sleep), how would I ensure it's cancelled after 5 sec? – NarūnasK Oct 26 '16 at 17:21
  • 2
    @NarūnasK Have a look at [loop.run_in_executor](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_in_executor) and this [answer about canceling a blocking call running in an executor](http://stackoverflow.com/questions/26413613/asyncio-is-it-possible-to-cancel-a-future-been-run-by-an-executor#26414982). – Vincent Oct 27 '16 at 11:53