Skip to main content
 首页 » 编程设计

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

2025年05月04日13lori

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

例如,here Tornado 的首席开发人员提到协程不应该引发异常,但不清楚原因。看起来这种方法有效并在 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 协程中引发异常是否有任何缺点,或者我们应该引发 gen.Return(exception_object) 吗?

请您参考如下方法:

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

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