【问题标题】:Raise exception or return gen.Return object in Tornado coroutine在 Tornado 协程中引发异常或返回 gen.Return 对象
【发布时间】:2017-05-12 09:27:27
【问题描述】:

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

例如,Tornado 的首席开发人员here 提到了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())

tornado.web.HTTPError 只是扩展了基础 Exception 类。此外,https://github.com/tornadoweb/tornado/issues/759#issuecomment-91817197 此处的讨论表明在协程内引发异常是合适的。

另外here,活跃的 Tornado 贡献者建议引发异常是好的:

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)

在 Tornado 协程中引发异常是否有任何不利之处,或者我们应该 raise gen.Return(exception_object) 吗?

【问题讨论】:

    标签: python tornado


    【解决方案1】:

    在 Python 2 中,仅使用 raise gen.Return(value) 返回正常值,不引发异常。它完全等同于 Python 3 中协程中的 return value

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

    【讨论】:

      【解决方案2】:

      在协程中引发异常是完全正常的。当我说“协程不应该引发异常”时,我指的是当您调用一个没有yieldawait 的协程时会发生什么:异常被捕获并保持到协程的返回值为yieldedawaited

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-27
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 2017-02-19
        • 2017-02-24
        • 1970-01-01
        相关资源
        最近更新 更多