Run async function after another one

224 views
Skip to first unread message

Corentin Leruth

unread,
Jan 28, 2015, 6:17:18 AM1/28/15
to python-...@googlegroups.com
Hello,

I would like to run 2 async function but the second after the first one has finished. For exemple:


do_something
Async_function1(param1, param2,..) Note that I don't yield this function because I don't need his result to continue
Async_function2(other_param1, other_param2, ..) Another async function who don't need the result of the first to run. But this function must be launched after the first is finished. I don't yield his result because I don't need this to continue
do_something2..

If I yield the 2 async_function, it's work but "do_something2" have to wait for their results and it's not necessary...

I tried with IOloop.add_future but the second async function don't need the Future from the first one. Each async_function have different param...


It's possible to achieve this behaviour ?

Thank you and sorry for my bad english :P

A. Jesse Jiryu Davis

unread,
Jan 28, 2015, 9:58:32 AM1/28/15
to python-...@googlegroups.com
You could just wrap async_function_1 and async_function_2 in another coroutine, and run it without yielding:

from tornado.ioloop import IOLoop
from tornado import gen


@gen.coroutine
def async_function_1():
    yield gen.sleep(1)
    print('async_function_1 done')


@gen.coroutine
def async_function_2():
    yield gen.sleep(1)
    print('async_function_2 done')


@gen.coroutine
def task():
    yield async_function_1()
    yield async_function_2()
    IOLoop.current().stop()  # Only for demonstration.


@gen.coroutine
def do_something_2():
    print('do_something_2 done')

@gen.coroutine
def do_something():
    task()
    yield do_something_2()
    print('do_something done')


do_something()
IOLoop.current().start()

To ensure you handle any exception thrown by task() you might do:

def handle_err(future):
    try:
        future.result()
    except Exception as e:
        # Log exception....
        pass

@gen.coroutine
def do_something():
    future = task()
    IOLoop.current().add_future(future, handle_err)
    yield do_something_2()
    print('do_something done')

--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornad...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ben Darnell

unread,
Jan 28, 2015, 2:11:31 PM1/28/15
to Tornado Mailing List
It's better to use IOLoop.spawn_callback than to simply call a coroutine without yielding it - this will avoid certain edge cases that can occur in exception handling, and gives you a default handler to log all errors (so you don't need to define a handle_err wrapper unless you want to do something else).

In other words:

  @gen.coroutine
  def do_something():
    # Note that there are no parens after 'task'; you're passing the 
    # function to spawn_callback, not calling it.
    IOLoop.current().spawn_callback(task)
    yield do_something2()

Reply all
Reply to author
Forward
0 new messages