Hello. I am a newbie at Sanic and Python3 async/coroutines.
I am trying to write a webserver that fetches a few urls in parallel (with a two seconds timeout) and returns the best result out of them. I have Sanic installed fine and I can run simpler code.
But since I started adding the async code to http get the urls, I'm getting this error:
2017-04-11 01:01:58,137: ERROR: Traceback (most recent call last):
File "/home/aiu/virtualenv/lib/python3.5/site-packages/sanic/app.py", line 391, in handle_request
response = await response
File "/usr/lib/python3.5/asyncio/coroutines.py", line 109, in __next__
return self.gen.send(None)
File "testurls.py", line 33, in adreq
done, not_done = asyncio.wait(tasks,timeout=2, return_when=ALL_COMPLETED)
File "/usr/lib/python3.5/asyncio/tasks.py", line 355, in wait
return (yield from _wait(fs, timeout, return_when, loop))
File "/usr/lib/python3.5/asyncio/tasks.py", line 438, in _wait
yield from waiter
File "uvloop/future.pyx", line 233, in __iter__ (uvloop/loop.c:110632)
AssertionError: yield from wasn't used with future
Unfortunately I don't understand where's the problem and Google offers little help.
Could anyone point out what I'm doing wrong here?
Thanks. Below is the code.
import asyncio
import uvloop
from aiohttp import ClientSession
from sanic_useragent import SanicUserAgent
from urllib.parse import urlencode, urlunparse
from concurrent.futures import ALL_COMPLETED
import aiohttp
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
from sanic import Sanic
from sanic.response import json
loop = None
app = Sanic(__name__)
SanicUserAgent.init_app(app)
async def fetch(url):
async with ClientSession() as session:
async with session.get(url) as response:
return await response.read()
@app.route("/")
async def adreq(request):
urls = ["http://www.google.com","http://www.cnn.com","http://www.nydailynews.com/"]
tasks = []
for u in urls:
task = asyncio.ensure_future(fetch(u))
#task = loop.create_task(fetch(u))
tasks.append(task)
done, not_done = asyncio.wait(tasks,timeout=2, return_when=ALL_COMPLETED)
return json(done)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
app.run(host="0.0.0.0", port=8000, workers=3, debug=True, loop=loop)
done, not_done = await asyncio.wait(tasks,timeout=2, return_when=ALL_COMPLETED)
asyncio.wait is a coroutine function
https://docs.python.org/3/library/asyncio-task.html?highlight=wait#asyncio.wait
That fixed it. Thanks a lot!
@aiurlano How did you fix the above issue? Can you please share code change you did?
@11ash99 I don't really remember now but I think It was enough to add the await keyword before asyncio.wait call
Most helpful comment
asyncio.waitis a coroutine functionhttps://docs.python.org/3/library/asyncio-task.html?highlight=wait#asyncio.wait