我正在使用 python 3.4.3 定期向多个 url 发送请求。这是我编写的协程(我省略了一些错误处理以简化代码):
@asyncio.coroutine
def ping(url, interval, session, *, loop):
while True:
try:
with aiohttp.Timeout(interval):
resp = yield from session.get(url)
resp.close()
except asyncio.TimeoutError:
# continue sending requests anyway
continue
yield from asyncio.sleep(interval)
我正在ping
使用asyncio.gather
. 但有时当服务器响应时间过长时,我会遇到InvalidStateError
异常:
Exception in callback <bound method Future.set_result of Future<CANCELLED>>(None,)
handle: Handle(<bound method Future.set_result of Future<CANCELLED>>, (None,))
Traceback (most recent call last):
File "/usr/lib/python3.4/asyncio/events.py", line 39, in _run
self._callback(*self._args)
File "/usr/lib/python3.4/asyncio/futures.py", line 298, in set_result
raise InvalidStateError('{}: {!r}'.format(self._state, self))
asyncio.futures.InvalidStateError: CANCELLED: Future<CANCELLED>
该脚本继续工作,但我怎样才能使这个回溯保持沉默?这是一个错误还是我做错了什么?
我唯一的想法是,当 Web 服务器最终响应时,asyncio(或 aiohttp)会尝试将 restult 设置Future
为已经取消的那个。
编辑:
这是我启动该ping
协程的方式:
@asyncio.coroutine
def main(loop, rules, session):
tasks = [ping(url, interval, session, loop=loop)
for url, interval in rules]
try:
yield from asyncio.gather(*tasks, loop=loop)
except Exception:
print('Cancelled!', file=sys.stderr)
traceback.print_exc()
if __name__ == '__main__':
rules = [('http://localhost:8080/1/', 5),
('http://localhost:8080/2/', 10)]
loop = asyncio.get_event_loop()
try:
conn = aiohttp.TCPConnector(verify_ssl=False)
with aiohttp.ClientSession(connector=conn) as session:
loop.run_until_complete(main(loop=loop,
rules=rules,
session=session))
except KeyboardInterrupt:
print('Interrupted. Exiting', file=sys.stderr)