Here is a toy example that downloads the home page from several websites using asyncio and aiohttp:
import asyncio
import aiohttp
sites = [
"http://google.com",
"http://reddit.com",
"http://wikipedia.com",
"http://afpy.org",
"http://httpbin.org",
"http://stackoverflow.com",
"http://reddit.com"
]
async def main(sites):
for site in sites:
download(site)
async def download(site):
response = await client.get(site)
content = await response.read()
print(site, len(content))
loop = asyncio.get_event_loop()
client = aiohttp.ClientSession(loop=loop)
content = loop.run_until_complete(main(sites))
client.close()
If I run it, I get:
RuntimeWarning: coroutine 'download' was never awaited
But I don't want to await it.
In twisted I can do:
for site in sites:
download(site)
And If I don't explicitly "yield" or add a callback to the returned Deferred, it just runs without blocking nor complaining. I can't access the result, but in this case I don't need it.
In JS I can do:
site.forEarch(site){
donwload(site)
}
And again, it doesn't block nor does it requires anything from my part.
I found a way to do:
async def main(sites):
await asyncio.wait([download(site) for site in sites])
But:
It there a better way ?
Run an asyncio Event Loop run_until_complete(<some Future object>) – this function runs a given Future object, usually a coroutine defined by the async / await pattern, until it's complete. run_forever() – this function runs the loop forever. stop() – the stop function stops a running loop.
Instead of await ing the coroutine, call asyncio. create_task to spawn a task object that runs in the background. At your next iteration you can check if the task is done and await/cancel it accordingly. (Otherwise asyncio will complain of un-awaited tasks being garbage collected.)
Run the event loop until stop() is called. If stop() is called before run_forever() is called, the loop will poll the I/O selector once with a timeout of zero, run all callbacks scheduled in response to I/O events (and those that were already scheduled), and then exit.
The keyword await passes function control back to the event loop. (It suspends the execution of the surrounding coroutine.) If Python encounters an await f() expression in the scope of g() , this is how await tells the event loop, “Suspend execution of g() until whatever I'm waiting on—the result of f() —is returned.
In order to schedule a coroutine as a task, use asyncio.ensure_future:
for site in sites:
coro = download(site)
future = asyncio.ensure_future(coro)
It replaces the deprecated function asyncio.async in version 3.4.4.
Then you can manage those futures using await
, asyncio.wait or asyncio.gather.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With