从concurrent.futures到ASYNCIO
问题描述:
我有两个问题concurrent.futures:从concurrent.futures到ASYNCIO
如何突破time.sleep()在Python concurrent.futures?
结论:time.sleep()不能被打断。一个解决方案是:你可以在它周围写一个循环,并做短暂的睡眠。
见How to break time.sleep() in a python concurrent.futures
个人超时的concurrent.futures?
结论:个别超时需要由用户执行。例如:对于每个超时,您可以拨打wait()。
见Individual timeouts for concurrent.futures
问题
是否asyncio解决问题的论文?
答
在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