在Tornado协程中引发异常或返回gen.Return对象

two*_*e88 1 python tornado

我们有一个Python 2项目,我们积极使用协同程序.我们找不到关于协程内部异常处理的任何指南.

例如,在这里龙卷风的主要开发人员提到coroutines should never raise an exception,但目前尚不清楚为什么.看起来这种方法可以在Tornado.web本身中使用并大量使用:

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())
Run Code Online (Sandbox Code Playgroud)

tornado.web.HTTPError只是扩展了基本的Exception类.另外,这里的讨论https://github.com/tornadoweb/tornado/issues/759#issuecomment-91817197建议在协程内提高异常是合适的.

同样在这里,活跃的龙卷风贡献者建议提高例外是好的:

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)
Run Code Online (Sandbox Code Playgroud)

在Tornado协同程序中提出异常是否有任何缺点,或者我们应该raise gen.Return(exception_object)吗?

A. *_*vis 6

在Python 2中,仅用于raise gen.Return(value)返回正常值,而不是引发异常.它完全相当于return valuePython 3中的协程.

要从协程引发异常,正常raise Exception()是正确的.关于协同程序的奇妙之处在于它们的异常处理语义与常规函数几乎相同.