Skip to content

Instantly share code, notes, and snippets.

@mikhail
Last active August 29, 2015 14:08
Show Gist options
  • Save mikhail/f9a82fda67b6089af3d5 to your computer and use it in GitHub Desktop.
Save mikhail/f9a82fda67b6089af3d5 to your computer and use it in GitHub Desktop.
Tornado firing vs yielding

Yielding a list of tasks in Tornado 4.0

Note: This behavior has changed in Tornado 4.1

Executing python yield_all.py will produce results similar to:

$ python run_all.py
one is sleeping
two is sleeping
three is sleeping
four is sleeping
Beginning yield
four is raising exception!
two is raising exception!
three is raising exception!
one is raising exception!
Traceback (most recent call last):
  File "run_all.py", line 48, in <module>
    ioloop.IOLoop.instance().run_sync(raise_many)
  File "run_all.py", line 30, in raise_many
    yield tasks
  File "run_all.py", line 18, in raise_exception
    raise Exception('Bad things from %s' % name)
Exception: Bad things from one

Note two important things:

  1. "Beginning yield" starts after the sleeping has been initiated.
  2. The traceback you see is always from one and not from a random name.
import random
import time
from tornado import gen
from tornado import ioloop
@gen.coroutine
def tornado_sleep(seconds=1.0):
yield gen.Task(ioloop.IOLoop.current().add_timeout,
time.time() + seconds)
@gen.coroutine
def raise_exception(name):
print "%s is sleeping" % name
seconds = random.random()
yield tornado_sleep(seconds)
print "%s is raising exception!" % name
raise Exception('Bad things from %s' % name)
@gen.coroutine
def raise_many():
tasks = [raise_exception('one'),
raise_exception('two'),
raise_exception('three'),
raise_exception('four')]
errors = []
print "Beginning yield"
yield tasks
def print_tidy_exception(e):
# Skip traceback that involves site-packages.
import traceback
trace_lines = traceback.format_exc(e).splitlines()
skip_next = False
for l in trace_lines:
if 'tornado' in l:
skip_next = True
continue
if not skip_next:
print(l)
skip_next = False
if __name__ == '__main__':
try:
ioloop.IOLoop.instance().run_sync(raise_many)
except Exception as e:
print_tidy_exception(e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment