{"action":"created","issue":{"url":"https://api.github.com/repos/python/asyncio/issues/253","labels_url":"https://api.github.com/repos/python/asyncio/issues/253/labels{/name}","comments_url":"https://api.github.com/repos/python/asyncio/issues/253/comments","events_url":"https://api.github.com/repos/python/asyncio/issues/253/events","html_url":"https://github.com/python/asyncio/issues/253","id":93899929,"number":253,"title":"wait_for() seems to not cancel the task, or cancels it in the wrong order.","user":{"login":"realazthat","id":141522,"avatar_url":"https://avatars.githubusercontent.com/u/141522?v=3","gravatar_id":"","url":"https://api.github.com/users/realazthat","html_url":"https://github.com/realazthat","followers_url":"https://api.github.com/users/realazthat/followers","following_url":"https://api.github.com/users/realazthat/following{/other_user}","gists_url":"https://api.github.com/users/realazthat/gists{/gist_id}","starred_url":"https://api.github.com/users/realazthat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/realazthat/subscriptions","organizations_url":"https://api.github.com/users/realazthat/orgs","repos_url":"https://api.github.com/users/realazthat/repos","events_url":"https://api.github.com/users/realazthat/events{/privacy}","received_events_url":"https://api.github.com/users/realazthat/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2015-07-08T21:58:49Z","updated_at":"2015-07-09T20:37:39Z","closed_at":"2015-07-09T15:06:55Z","body":"Here is an example:\r\n\r\n    @asyncio.coroutine\r\n    def something(sleep,marker):\r\n\r\n        try:\r\n            print ('something() is sleeping for %s  seconds!' % sleep,flush=True)\r\n            yield from asyncio.sleep(sleep)\r\n        finally:\r\n            print ('cleaning something()!',flush=True)\r\n            marker['cleaned'] = True\r\n\r\n    @asyncio.coroutine\r\n    def test_session2():\r\n        marker = {'cleaned': False}\r\n        yield from asyncio.wait_for(something(5, marker), timeout=10)\r\n        #here something is cleaned up\r\n\r\n        try:\r\n            marker = {'cleaned': False}\r\n            yield from asyncio.wait_for(something(10, marker), timeout=5)\r\n        except asyncio.TimeoutError:\r\n            print ('something() has timed out')\r\n            pass\r\n        #here something is not cancelled yet ... it cancels later.\r\n        #intuitively, you'd think that wait_for would throw after something() is actually cancelled\r\n        print ('is something cleaned up?', ('YES!' if marker['cleaned'] else 'NO!'))\r\n        print ('sleeping a bit')\r\n        yield from asyncio.sleep(1)\r\n        print ('is something cleaned up?', ('YES!' if marker['cleaned'] else 'NO!'))\r\n\r\n    loop = asyncio.get_event_loop()\r\n\r\n    loop.run_until_complete(test_session2())\r\n\r\nAnd the output:\r\n\r\n\r\n    $ python3 asyncio.wait_for.test.py\r\n    something() is sleeping for 5  seconds!\r\n    cleaning something()!\r\n    something() is sleeping for 10  seconds!\r\n    something() has timed out\r\n    is something cleaned up? NO!\r\n    sleeping a bit\r\n    cleaning something()!\r\n    is something cleaned up? YES!\r\n\r\nSo `wait_for()` throws `TimeoutError`, but the coroutine is not yet cancelled.\r\n\r\nBasically, I think that the task should first be cancelled, and then `wait_for()` should return.\r\n\r\nOR.\r\n\r\nIt should be more explicitly documented that the task will cancel, but not necessarily before `wait_for()` raises an error.\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/python/asyncio/issues/comments/120138132","html_url":"https://github.com/python/asyncio/issues/253#issuecomment-120138132","issue_url":"https://api.github.com/repos/python/asyncio/issues/253","id":120138132,"user":{"login":"haypo","id":194129,"avatar_url":"https://avatars.githubusercontent.com/u/194129?v=3","gravatar_id":"","url":"https://api.github.com/users/haypo","html_url":"https://github.com/haypo","followers_url":"https://api.github.com/users/haypo/followers","following_url":"https://api.github.com/users/haypo/following{/other_user}","gists_url":"https://api.github.com/users/haypo/gists{/gist_id}","starred_url":"https://api.github.com/users/haypo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haypo/subscriptions","organizations_url":"https://api.github.com/users/haypo/orgs","repos_url":"https://api.github.com/users/haypo/repos","events_url":"https://api.github.com/users/haypo/events{/privacy}","received_events_url":"https://api.github.com/users/haypo/received_events","type":"User","site_admin":false},"created_at":"2015-07-09T20:37:39Z","updated_at":"2015-07-09T20:37:39Z","body":"> Note that wait_for() does not wait until the task is cancelled.\r\n\r\nThis sentence is unclear, or wrong.\r\n\r\nIf a task is cancelled, wait_for() immediatly returns (raise CancelledError).\r\n\r\nIf wait_for() is used on a task and a task doesn't complete before the timeout, the task is cancelled. The problem is that the cancellation is only \"scheduled\": cancelled() returns False. It's counter intuitive.\r\n\r\nA shorter example is: \"task.cancel(); assert not task.cancelled()\".\r\n\r\nOk, I now have a better understanding of the documentation issue."}}