在asyncio模型中,執行是由事件循環調度和協調的。要取消執行當前掛起的任務,你基本上只需要就不會恢復它。雖然這在實踐中有點不同,但顯而易見的是,這使得在理論上取消暫停的任務變得簡單。單獨的超時當然可能是相同的:每當你暫停一個協程來等待一個結果時,你想提供一個超時值。事件循環將確保在達到超時並且任務尚未完成時取消正在等待的任務。
一些具體的示例:
class Foo:
task = None
async def sleeper(self):
self.task = asyncio.sleep(60)
try:
await self.task
except concurrent.futures.CancelledError:
raise NotImplementedError
雖然這種方法是睡着了,別人可以撥打foo.task.cancel()
喚醒協程:
>>> import asyncio
>>> loop = asyncio.get_event_loop()
>>> task = asyncio.ensure_future(asyncio.sleep(5))
>>> task.cancel()
>>> loop.run_until_complete(task)
Traceback (most recent call last):
...
concurrent.futures._base.CancelledError
在實踐中,這可能會使用這樣的事情來實現並讓它處理取消。或者,撥打sleeper()
的人可以直接取消它,但不給它一個清理機會。
設置超時也同樣簡單:
>>> loop.run_until_complete(asyncio.wait_for(asyncio.sleep(60), 5))
[ ... 5 seconds later ... ]
Traceback (most recent call last):
...
concurrent.futures._base.TimeoutError
特別是在HTTP請求超時的情況下,看到aiohttp:
async def fetch_page(session, url):
with aiohttp.Timeout(10):
async with session.get(url) as response:
assert response.status == 200
return await response.read()
with aiohttp.ClientSession(loop=loop) as session:
content = loop.run_until_complete(fetch_page(session, 'http://python.org'))
顯然每次調用fetch_page
可以自行aiohttp.Timeout
價值決定,並當達到超時時,每個單獨的實例將拋出它自己的異常。
爲了自我控制,你能在這裏總結其他兩個問題嗎? – deceze
@deceze,我更新了問題並添加了我的結論。這是好的,還是缺少一些東西? – guettli
現在看起來更多,謝謝。 – deceze