So I had a code block that looked like this in my Tornado app:
fetch_results = yield {
'itemOne': make_network_call_one(),
'itemTwo': make_network_call_two(),
'itemThree': make_network_call_three()
}
These three network calls are obviously async.
Now, I have a bool
that tells me whether I need to actually make these network calls.
For instance:
if should_fetch_item_one:
item_one = yield make_network_call_one()
if should_fetch_item_two:
item_two = yield make_network_call_two()
if should_fetch_item_three:
item_three = yield make_network_call_three()
What is the best/most-Pythonic way to do this in a still-async manner? (I realize I could check all possible combinations of the three bools and yield an object like the first code block, but I'd prefer to avoid this.)
(I'm on Python 2.7)
How about this?:
from tornado.concurrent import Future
from tornado import gen
@gen.coroutine
def f():
resolved = Future()
resolved.set_result(None)
tasks = {}
tasks['itemOne'] = make_network_call_one() if should_make_call_one else resolved
tasks['itemTwo'] = make_network_call_two() if should_make_call_two else resolved
tasks['itemThree'] = make_network_call_three() if should_make_call_three else resolved
results = yield tasks
The point of "resolved" is to ensure your "tasks" dictionary always has the same three keys: "itemOne", "itemTwo", and "itemThree". All the values in "tasks" are Futures: either the futures returned by coroutines like make_network_call_one
, or the "resolved" Future.
Yielding the dictionary pauses your coroutine until all operations are complete. In the case of "resolved" it's already complete and its value is None, in the case of make_network_call_one
and so on, the operations may take some time. "results" is now a dict with the same set of keys as "tasks", but all the Futures in "tasks" are replaced by values.