Reputation: 1452
If I have something like the following:
@tornado.gen.coroutine
def first(x):
#
# do stuff
for i in I:
tornado.ioloop.IOLoop.current().spawn_callback(func,i)
tornado.ioloop.IOLoop.current().spawn_callback(func2,z)
yield first(xxx)
Can I be guaranteed that all the spawned functions in the for
loop will run before the last spawning of callback to func2()?
Upvotes: 1
Views: 2950
Reputation: 24007
No, in fact you're guaranteed that all the functions are spawned before any of them starts running, because first
does not yield
between spawning func
and spawning func2
. You can verify this yourself by testing your code:
from tornado import gen, ioloop
@gen.coroutine
def func():
print('func started')
yield gen.moment
print('func done')
@gen.coroutine
def func2():
print('func2 started')
yield gen.moment
print('func2 done')
@gen.coroutine
def first():
for i in range(2):
ioloop.IOLoop.current().spawn_callback(func)
ioloop.IOLoop.current().spawn_callback(func2)
yield gen.sleep(1)
ioloop.IOLoop.current().run_sync(first)
It prints:
func started
func started
func2 started
func done
func done
func2 done
See, func2
begins before the coroutines running func
complete.
To accomplish what you want:
@gen.coroutine
def first():
yield [func() for i in range(2)]
ioloop.IOLoop.current().spawn_callback(func2)
This prints:
func started
func started
func done
func done
func2 started
func2 done
If you want first
to wait for func2
to finish before it exits, then:
@gen.coroutine
def first():
yield [func() for i in range(2)]
yield func2()
For more info on calling coroutines from coroutines, see my Refactoring Tornado Coroutines.
Upvotes: 8