Reputation: 1629
So, I'm just trying to wrap my head around async programming (in particular the Tornado framework), and thought I'd start with the basics: calling "awaiting" on two coroutines:
from tornado.ioloop import IOLoop
from tornado.web import Application, url, RequestHandler
from tornado.gen import sleep
class TestHandler(RequestHandler):
async def get(self):
f1 = await self.test("f1")
f2 = await self.test("f2")
self.write(f1 + " " + f2)
async def test(self, msg):
for i in range(5):
print(i)
await sleep(1) # this is tornado's async sleep
return msg
app = Application([url(r'/', TestHandler)], debug=True)
app.listen(8080)
ioloop = IOLoop.current()
ioloop.start()
The issue, however, is that when I hit localhost:8080
in my browser, and stare at my python console, I don't see two interwoven sequences of 0 1 2 3 4
, but two sequential sequences...
I've read the Tornado FAQ over-and-over again and can't seem to understand what I'm doing wrong.
Upvotes: 0
Views: 817
Reputation: 8673
The multi
function accepts lists and dicts whose values are Futures
, and waits for all of those Futures
in parallel:
from tornado.gen import multi
async def parallel_fetch(url1, url2):
resp1, resp2 = await multi([http_client.fetch(url1),
http_client.fetch(url2)])
async def parallel_fetch_many(urls):
responses = await multi ([http_client.fetch(url) for url in urls])
# responses is a list of HTTPResponses in the same order
async def parallel_fetch_dict(urls):
responses = await multi({url: http_client.fetch(url)
for url in urls})
# responses is a dict {url: HTTPResponse}
Upvotes: 0
Reputation: 22154
This runs f1
, waits for it to finish, then runs f2
:
f1 = await self.test("f1")
f2 = await self.test("f2")
To run things in parallel, you can't await
the first one before starting the second. The simplest way to do this is to do them both in one await
:
f1, f2 = await tornado.gen.multi(self.test("f1"), self.test("f2"))
Or in advanced cases, you can start f1
without waiting for it then come back to wait for it later:
f1_future = tornado.gen.convert_yielded(self.test("f1"))
f2_future = tornado.gen.convert_yielded(self.test("f2"))
f1 = await f1_future
f2 = await f2_future
Upvotes: 3