Python asyncio force timeout
python, python-asyncio
Solution
No, you can't interrupt a coroutine unless it yields control back to the event loop, which means it needs to be inside a `yield from` call. `asyncio` is single-threaded, so when you're blocking on the `time.sleep(10)` call in your second example, there's no way for the event loop to run. That means when the timeout you set using `wait_for` expires, the event loop won't be able to take action on it. The event loop doesn't get an opportunity to run again until `coro` exits, at which point its too late.
This is why in general, you should always avoid any blocking calls that aren't asynchronous; any time a call blocks without yielding to the event loop, nothing else in your program can execute, which is probably not what you want. If you really need to do a long, blocking operation, you should try to use `BaseEventLoop.run_in_executor` to run it in a thread or process pool, which will avoid blocking the event loop:
import asyncio
import time
from concurrent.futures import ProcessPoolExecutor
@asyncio.coroutine
def coro(loop):
ex = ProcessPoolExecutor(2)
yield from loop.run_in_executor(ex, time.sleep, 10) # This can be interrupted.
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait_for(coro(loop), 1))
Problem
Using asyncio a coroutine can be executed with a timeout so it gets cancelled after the timeout: ``` @asyncio.coroutine def coro(): yield from asyncio.sleep(10) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait_for(coro(), 5)) ``` The above example works as expected (it times out after 5 seconds). However, when the coroutine doesn't use `asyncio.sleep()` (or other asyncio coroutines) it doesn't seem to time out. Example: ``` @asyncio.coroutine def coro(): import time time.sleep(10) loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait_for(coro(), 1)) ``` This takes more than 10 seconds to run because the `time.sleep(10)` isn't cancelled. Is it possible to enforce the cancellation of the coroutine in such a case? If asyncio should be used to solve this, how could I do that?