我有下面这段代码,使用asyncio
和aiohttp
来进行异步的HTTP请求。
import sys
import asyncio
import aiohttp
@asyncio.coroutine
def get(url):
try:
print('GET %s' % url)
resp = yield from aiohttp.request('GET', url)
except Exception as e:
raise Exception("%s has error '%s'" % (url, e))
else:
if resp.status >= 400:
raise Exception("%s has error '%s: %s'" % (url, resp.status, resp.reason))
return (yield from resp.text())
@asyncio.coroutine
def fill_data(run):
url = 'http://www.google.com/%s' % run['name']
run['data'] = yield from get(url)
def get_runs():
runs = [ {'name': 'one'}, {'name': 'two'} ]
loop = asyncio.get_event_loop()
task = asyncio.wait([fill_data(r) for r in runs])
loop.run_until_complete(task)
return runs
try:
get_runs()
except Exception as e:
print(repr(e))
sys.exit(1)
由于某些原因,在get
函数内引发的异常不会被捕获:
Future/Task exception was never retrieved
Traceback (most recent call last):
File "site-packages/asyncio/tasks.py", line 236, in _step
result = coro.send(value)
File "mwe.py", line 25, in fill_data
run['data'] = yield from get(url)
File "mwe.py", line 17, in get
raise Exception("%s has error '%s: %s'" % (url, resp.status, resp.reason))
Exception: http://www.google.com/two has error '404: Not Found'
那么,正确处理由协程引发的异常的方法是什么?
wait
来实现呢?是像这样yield from asyncio.wait(...)
吗?await asyncio.wait(...)
也可以吗? - z0rawait <loop>.sock_recv(<socket>, <size>)
。如果套接字未切换到非阻塞模式(使用<socket>.setblocking()
),第二个协程将不会启动,而KeyboardInterrupt
将导致 "Task exception was never retrieved"。 - doakyield from
来解决 future 或 task。应该使用await
。这对我来说不是很清楚。 - Rugnarreturn_exceptions
提示。由于进行了数百个头请求,我不希望因其中一个超时而抛出异常。 - pouya