I have following situation:
callback
function using call_soon.callback
I would like to call another courotune, but end up with "frozen" callback.I will use modified Hello World with call_soon() to demonstrate this:
import asyncio
def hello_world(loop):
print('Hello')
# Call some coroutine.
yield from asyncio.sleep(5, loop=loop)
print('World')
loop.stop()
loop = asyncio.get_event_loop()
# Schedule a call to hello_world()
loop.call_soon(hello_world, loop)
# Blocking call interrupted by loop.stop()
loop.run_forever()
loop.close()
When I run this, nothing is being printed and the program never ends.
Ctrl+C
Traceback (most recent call last):
File "../soon.py", line 15, in <module>
loop.run_forever()
File "/usr/lib/python3.4/asyncio/base_events.py", line 276, in run_forever
self._run_once()
File "/usr/lib/python3.4/asyncio/base_events.py", line 1136, in _run_once
event_list = self._selector.select(timeout)
File "/usr/lib/python3.4/selectors.py", line 432, in select
fd_event_list = self._epoll.poll(timeout, max_ev)
KeyboardInterrupt
What is actually going on and why?
Any correct way to do this?
The example you mentioned demonstrate how to schedule a callback.
If you use the yield from
syntax, the function is actually a coroutine and it has to be decorated accordingly:
@asyncio.coroutine
def hello_world(loop):
print('Hello')
yield from asyncio.sleep(5, loop=loop)
print('World')
loop.stop()
Then you can schedule the coroutine as a task using ensure_future:
loop = asyncio.get_event_loop()
coro = hello_world(loop)
asyncio.ensure_future(coro)
loop.run_forever()
loop.close()
Or equivalently, using run_until_complete:
loop = asyncio.get_event_loop()
coro = hello_world(loop)
loop.run_until_complete(coro)
In two weeks, python 3.5 will officially be released and you'll be able to use the new async
/await
syntax:
async def hello_world(loop):
print('Hello')
await asyncio.sleep(5, loop=loop)
print('World')
EDIT: It is a bit ugly, but nothing prevents you from creating a callback that schedules your coroutine:
loop = asyncio.get_event_loop()
coro = hello_world(loop)
callback = lambda: asyncio.ensure_future(coro)
loop.call_soon(callback)
loop.run_forever()
loop.close()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With