Reputation: 2871
We have a Python 2 project where we actively use coroutines. We can't find any guidelines on exceptions handling inside coroutines.
For example, here lead developer of Tornado mentioned that coroutines should never raise an exception
, but it is not clear why. Looks like this approach works and heavily used in Tornado.web itself:
https://github.com/tornadoweb/tornado/blob/master/demos/blog/blog.py#L180
class AuthCreateHandler(BaseHandler):
def get(self):
self.render("create_author.html")
@gen.coroutine
def post(self):
if self.any_author_exists():
raise tornado.web.HTTPError(400, "author already created")
hashed_password = yield executor.submit(
bcrypt.hashpw, tornado.escape.utf8(self.get_argument("password")),
bcrypt.gensalt())
tornado.web.HTTPError just extends base Exception class. Also, discussion here https://github.com/tornadoweb/tornado/issues/759#issuecomment-91817197 suggests that raising exception inside coroutine is appropriate.
Also here, active Tornado contributor suggests that raising exceptions is fine:
class PostHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self, slug):
post = yield db.posts.find_one({'slug': slug})
if not post:
raise tornado.web.HTTPError(404)
self.render('post.html', post=post)
Is there any downsides to raising exceptions inside Tornado coroutines or should we raise gen.Return(exception_object)
?
Upvotes: 1
Views: 2841
Reputation: 22154
Raising exceptions inside coroutines is perfectly normal. When I said "coroutines should never raise an exception" I was referring to what happens when you call a coroutine without yield
or await
: The exception is captured and held until the coroutine's return value is either yielded
or awaited
.
Upvotes: 4
Reputation: 24007
In Python 2, only use raise gen.Return(value)
to return a normal value, not to raise an exception. It is exactly the equivalent of return value
in a coroutine in Python 3.
To raise an exception from a coroutine, a normal raise Exception()
is correct. The wonderful thing about coroutines is their exception-handling semantics are pretty much the same as regular functions.
Upvotes: 8