Search code examples
pythonasynchronoustornado

Python Tornado -- Make calls async?


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)


Solution

  • 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.